Purify and Java

Contents
  • Purify 4.1-beta instructions
  • Purify/JNI Sample Code
  • JDK1.2beta2 and Purify
  • Purify/JNI/Tcl
  • Using Purify to check for memory leaks in a Java JNI program is a little tricky.

    Purify 4.1-beta instructions

    Under Solaris, Purify-4.0.1 did not work for me, I had to contact support@rational.com and get Purify version 4.1-beta-L3 971120 Solaris 2.

    I was told via email from support@rational.com, that to get purify'd jvm working, I needed to:

  • Add to .purify (in current directory or your home directory) before instrumenting (only libjava.so, not needed for libjava_g.so):
    ignore set_single_stepping libjava.so
    registercode nop_0+0x0 Illegal254_0+0x3c libjava.so
    
  • Link in solaris_threads.so with the executable. This is needed for both libjava.so and libjava_g.so.
  • Run Purify with (for both libjava.so and libjava_g.so): setenv PURIFYOPTIONS "-ignore_signals=SIGPOLL -threads=yes -use_internal_locks=yes"
  • The above steps worked fine for JDK1.1.4 with native and green threads.

    Local Notes

  • Locally, the beta version of purify is located at /usr/eesww/pure/purify.
  • To run the purify'd binary, I found it necessary to explicitly set the CLASSPATH variable from the shell prompt. Setting CLASSPATH in the makefile did not seem to work.
  • I find the following suppressions useful. These can go in either ~/.purify or ./purify.
    suppress umr GetDefaultClassPath
    suppress umr ResolveClassConstant
    suppress umr ExecuteJava
    suppress umr quickInvocation
    suppress umr execute_java_constructor
    suppress umr do_execute_java_method_vararg
    suppress umr sysThreadAlloc
    suppress umr sysDynamicLink
    suppress umr quickStaticAccess
    suppress umr Java_java_lang_System_arraycopy_stub
    suppress umr Java_java_lang_Class_getPrimitiveClass_stub
    suppress umr fillInStackTrace
    suppress umr ProcedureFindThrowTag
    suppress umr FindClass
    suppress umr mktime; zip_stat
    suppress umr qst; qsort; initReader
    

  • Purify/JNI Sample Code

    jnihello.tar contains source code that build a C executable that invokes a Java method which prints a message. A purified version is also built.
  • makefile
  • Prog.java
  • invoke.c

  • JDK1.2beta2 and Purify

    Unfortunately, Purify-4.1-beta-L3 fails with JDK1.2beta2.

    To try it with jnihello.tar:

    1. Download jnihello.tar.
    2. Edit the makefile and change JAVAHOME to point to your jdk1.2beta2 installation, and uncomment the JVM_LD_DIRECTIVE line
    3. Set CLASSPATH from the C Shell prompt:
      setenv CLASSPATH /opt/jdk1.2beta2/lib/classes.zip:.
      
    4. Run make
    What happens is that the process starts up and then goes into a busy loop. The last message is:
    ****  Purify instrumented invoke.purify (pid 13092)  ****
    PAR: Bad function parameter:
      * This is occurring while in:
    	DLOpEN         [rtlib.o]
    	sysFindBuiltinEntry [libjvm.so]
    	createInternalClass [libjvm.so]
    	LoadClassFromZip [classload.c]
    	LoadClassLocally [libjvm.so]
    	FindClassFromClass2 [libjvm.so]
      * dlopen("libjava.so", 257) file (arg #1) not found.
    
    Attaching to the process shows that it is hanging at:
    (gdb) bt
    #0  0x48254 in _p1061static ()
    #1  0x37cdc in _p914static ()
    #2  0x35c00 in _p246static ()
    #3  0x36368 in _p1106static ()
    #4  0x38360 in _libc_mmap ()
    #5  0xeeda9134 in _alloc_chunk ()
    #6  0xeeda8a30 in _alloc_stack ()
    #7  0xeedb3fb0 in _alloc_thread ()
    #8  0xeedae558 in _dynamic_create ()
    #9  0xeedb5184 in _t0init ()
    #10 0xeedbe278 in __pure_beg_ID_2c9a_34a596bf_36077_11_ID_obj_1__husr_hlib_hlibthread_gso_g1.a ()
    #11 0x303a4 in _p121static ()
    #12 0x303e0 in _p861static ()
    #13 0x30200 in _p1030static ()
    #14 0x237bc in DLOpEN ()
    #15 0xef7060a4 in TclLoadFile (interp=0x77e38, 
        fileName=0xefffdddc "/tmp_mnt/carson/carson1/cxh/java/tyjni/libtyjni.so", 
        sym1=0xefffdf8c "Tyjni_Init", sym2=0xefffdeb4 "Tyjni_SafeInit", 
        proc1Ptr=0xefffddcc, proc2Ptr=0xefffddc8)
        at /users/cxh/pt/src/tcltk/tcl8.0/unix/tclLoadDl.c:73
    #16 0xef6bb430 in Tcl_LoadCmd (dummy=0x0, interp=0x77e38, argc=2, 
        argv=0xefffe1b8)
        at /users/cxh/pt/src/tcltk/tcl8.0/unix/../generic/tclLoad.c:311
    

    Purify/JNI/Tcl

    I used Purify-4.1-beta to check for memory leaks in Tcl Blend.

    Tcl Blend uses a vanilla tclsh to load a shared object that contains an interface to Java. Unfortunately, this did not work, the purified tclsh binary hung during the call to dlopen().

    My workaround was to build a prebuilt tclsh image that had the Java JNI interface linked in. I added rules to create green.pure to the Tcl Blend unix/Makefile.in.

    1. Obtain and install Purify-4.1-beta3. Purify-4.0 will not work
    2. Build Tcl Blend as usual.
    3. Edit Makefile.in and change the PURIFYOPTIONS, PUREDIR, and PURIFY variables if necessary.
    4. Run green.pure.build in the build directory. You can ignore messages about attempted multiple inclusion of file.
    5. Run make test to compile the Java files used by the test suite.
    6. Run make green.pure.test.exec to run the tests.
  • .purify file that does some set up necessary for Purify to work with Java and then suppresses messages from within the JVM.
  • Output from running the Tcl Blend test suite under Purify

  • Last updated: 10/09/05 cxh at eecs