|
From: Tom S. <to...@pl...> - 2004-06-16 17:35:00
|
I have a mixed Java/C app that I am trying to run valgrind on. The
object of this exercise is to find a difficult-to-reproduct crash that
is related to JNI and garbage collection. Most of the C code is
valgrind clean, it is when it is used from JNI that I am having problems.
It is obvious to me that valgrind will not be able to run a standard
JVM, so I started looking into GCJ. GCJ will generate standard object
code that I should be able to run valgrind on. But I am stuck at the
starting gate.
Valgrind hangs when I try to initialize the GCJ Java runtime. It hangs
with both of the alternatives that GCJ provides, namely JvCreateJavaVM()
and JNI_CreateJavaVM(), although I suspect that one is just a wrapper
around the other.
Debian testing/unstable
Linux rota 2.6.3-1-686 #2 Tue Feb 24 20:24:38 EST 2004 i686 GNU/Linux
ii valgrind 2.1.1-3 A memory debugger for x86-linux
ii gcj-3.4 3.4.0-1 The GNU compiler for Java(TM)
ii gcc-3.4 3.4.0-1 The GNU C compiler
I have two easy test cases that follow. Both generated executables that
run, but when run under valgrind, they hang (using 100% cpu) when
initializing the Java runtime.
/* vg_cni.cc
* compile with:
* gcc-3.4 vg_cni.cc -o vg_cni -lgcj
*/
#include <gcj/cni.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
jint cni_error;
/* Initialize the Java runtime. */
printf("%s:%i\n", __FILE__, __LINE__);
cni_error = JvCreateJavaVM(NULL);
if (cni_error < 0) {
printf(
"ERROR: Unable to initialize the Java runtime, (%i)\n",
(int) cni_error
);
return(EXIT_FAILURE);
}
printf("%s:%i\n", __FILE__, __LINE__);
JvAttachCurrentThread(NULL, NULL);
printf("%s:%i\n", __FILE__, __LINE__);
JvDetachCurrentThread();
printf("%s:%i\n", __FILE__, __LINE__);
argc = argc;
argv = argv;
return(EXIT_SUCCESS);
}
/* vg_jni.c
* compile with:
* gcc-3.4 vg_jni.c -o vg_jni -lgcj
*/
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
JavaVMInitArgs vm_args;
JNIEnv *env = NULL;
JavaVM *jvm = NULL;
jint jni_error;
/* Setup the vm_args structure. */
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_2;
/* Create the Java Virtual Machine. */
printf("%s:%i\n", __FILE__, __LINE__);
jni_error = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args);
if (jni_error < 0) {
printf(
"ERROR: Unable to create Java Virtual Machine, (%i)\n",
(int) jni_error
);
return(EXIT_FAILURE);
}
printf("%s:%i\n", __FILE__, __LINE__);
if ((*env)->ExceptionOccurred(env)) {
printf("exception occurred %s:%i\n", __FILE__, __LINE__);
}
printf("%s:%i\n", __FILE__, __LINE__);
(*jvm)->DestroyJavaVM(jvm);
printf("%s:%i\n", __FILE__, __LINE__);
argc = argc;
argv = argv;
return(EXIT_SUCCESS);
}
$ valgrind vg_cni
==5831== Memcheck, a memory error detector for x86-linux.
==5831== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward.
==5831== Using valgrind-2.1.1, a program supervision framework for
x86-linux.
==5831== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.
==5831== For more details, rerun with: -v
==5831==
vg_cni.cc:14
==5831== Syscall param sigaction(act) contains uninitialised or
unaddressable byte(s)
==5831== at 0x3CA36025: __libc_sigaction (in /lib/tls/libc-2.3.2.so)
==5831== Address 0x4FFFE830 is on thread 1's stack
==5831==
==5831== Syscall param sigaction(act) contains uninitialised or
unaddressable byte(s)
==5831== at 0x3CA36025: __libc_sigaction (in /lib/tls/libc-2.3.2.so)
==5831== by 0x7FFFFFFB: ???
==5831== Address 0x4FFFE780 is on thread 1's stack
==5831==
==5831== Conditional jump or move depends on uninitialised value(s)
==5831== at 0x3C646535: GC_push_all_eager (in /usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C6478C9: GC_push_current_stack (in
/usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C64E12D: GC_generic_push_regs (in
/usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C6479FD: GC_push_roots (in /usr/lib/libgcj.so.5.0.0)
==5831==
==5831== Conditional jump or move depends on uninitialised value(s)
==5831== at 0x3C64653A: GC_push_all_eager (in /usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C6478C9: GC_push_current_stack (in
/usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C64E12D: GC_generic_push_regs (in
/usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C6479FD: GC_push_roots (in /usr/lib/libgcj.so.5.0.0)
==5831==
==5831== Conditional jump or move depends on uninitialised value(s)
==5831== at 0x3C646535: GC_push_all_eager (in /usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C6465B9: GC_push_all_stack (in /usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C64DB96: GC_push_all_stacks (in /usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C649815: GC_default_push_other_roots (in
/usr/lib/libgcj.so.5.0.0)
==5831==
==5831== Syscall param sigaction(act) contains uninitialised or
unaddressable byte(s)
==5831== at 0x3CAE551D: syscall (in /lib/tls/libc-2.3.2.so)
==5831== by 0x8048736: JvCreateJavaVM(void*) (in
/home/tom/tmp/valgrind_gcj/vg_cni)
==5831== by 0x8048670: main (in /home/tom/tmp/valgrind_gcj/vg_cni)
==5831== Address 0x4FFFE9B0 is on thread 1's stack
==5831==
==5831== Conditional jump or move depends on uninitialised value(s)
==5831== at 0x3C64D25C: GC_pthread_create (in /usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C472162: _Jv_ThreadStart(java::lang::Thread*,
_Jv_Thread_t*, void (*)(java::lang::Thread*)) (in /usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C49E6A6: java::lang::Thread::start() (in
/usr/lib/libgcj.so.5.0.0)
==5831== by 0x3C473E09: _Jv_CreateJavaVM(void*) (in
/usr/lib/libgcj.so.5.0.0)==5831==
==5831== Thread 2:
==5831== Conditional jump or move depends on uninitialised value(s)
==5831== at 0x3CB4CFF1: thread_wrapper (vg_libpthread.c:824)
==5831== by 0xB800FACC: do__quit (vg_scheduler.c:1792)
==5831==
==5831== Thread 2:
==5831== thread_wrapper: invalid attr->__detachstate
==5831== at 0x3CB4C00F: pthread_error (vg_libpthread.c:355)
==5831== by 0x3CB4D000: thread_wrapper (vg_libpthread.c:826)
==5831== by 0xB800FACC: do__quit (vg_scheduler.c:1792)
==5831==
==5831== Thread 2:
==5831== Conditional jump or move depends on uninitialised value(s)
==5831== at 0x3CB4D004: thread_wrapper (vg_libpthread.c:827)
==5831== by 0xB800FACC: do__quit (vg_scheduler.c:1792)
------------------------hangs here-----------------------------
--
Tom Schutter (mailto:to...@pl...)
Platte River Associates, Inc. (http://www.platte.com)
|
|
From: Jeroen N. W. <jn...@xs...> - 2004-06-18 09:03:40
|
Tom (and list),
I am not an expert on valgrind, Java, JNI or GCJ, so I have no answers,
just a few questions and comments, inlined below.
> I have a mixed Java/C app that I am trying to run valgrind on. The
> object of this exercise is to find a difficult-to-reproduct crash that
> is related to JNI and garbage collection. Most of the C code is
> valgrind clean, it is when it is used from JNI that I am having problems.
>
> It is obvious to me that valgrind will not be able to run a standard
> JVM, [...]
Do you have any evidence to support this statement? I am able to run
`valgrind --tool=memcheck -v java` on a simple Java application that does
not use JNI, without any problems, errors or warnings.
> [...] so I started looking into GCJ. GCJ will generate standard object
> code that I should be able to run valgrind on. [...]
Correct, but there is no guarantee that running this compiled version of
your application will fail in the same way, or even fail at all. The way
the JVM and GCJ implement garbage collection probably is not identical.
> But I am stuck at the
> starting gate.
Somebody else will have to look at your problem with valgrind and GCJ,
quoted below; it is beyond my scope.
Cheers,
Jeroen.
> Valgrind hangs when I try to initialize the GCJ Java runtime. It hangs
> with both of the alternatives that GCJ provides, namely JvCreateJavaVM()
> and JNI_CreateJavaVM(), although I suspect that one is just a wrapper
> around the other.
>
> Debian testing/unstable
> Linux rota 2.6.3-1-686 #2 Tue Feb 24 20:24:38 EST 2004 i686 GNU/Linux
> ii valgrind 2.1.1-3 A memory debugger for x86-linux
> ii gcj-3.4 3.4.0-1 The GNU compiler for Java(TM)
> ii gcc-3.4 3.4.0-1 The GNU C compiler
>
> I have two easy test cases that follow. Both generated executables that
> run, but when run under valgrind, they hang (using 100% cpu) when
> initializing the Java runtime.
>
> /* vg_cni.cc
> * compile with:
> * gcc-3.4 vg_cni.cc -o vg_cni -lgcj
> */
>
> #include <gcj/cni.h>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main(int argc, char *argv[]) {
> jint cni_error;
>
> /* Initialize the Java runtime. */
> printf("%s:%i\n", __FILE__, __LINE__);
> cni_error = JvCreateJavaVM(NULL);
> if (cni_error < 0) {
> printf(
> "ERROR: Unable to initialize the Java runtime, (%i)\n",
> (int) cni_error
> );
> return(EXIT_FAILURE);
> }
>
> printf("%s:%i\n", __FILE__, __LINE__);
> JvAttachCurrentThread(NULL, NULL);
>
> printf("%s:%i\n", __FILE__, __LINE__);
> JvDetachCurrentThread();
>
> printf("%s:%i\n", __FILE__, __LINE__);
> argc = argc;
> argv = argv;
> return(EXIT_SUCCESS);
> }
>
>
> /* vg_jni.c
> * compile with:
> * gcc-3.4 vg_jni.c -o vg_jni -lgcj
> */
>
> #include <jni.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> int main(int argc, char *argv[]) {
> JavaVMInitArgs vm_args;
> JNIEnv *env = NULL;
> JavaVM *jvm = NULL;
> jint jni_error;
>
> /* Setup the vm_args structure. */
> memset(&vm_args, 0, sizeof(vm_args));
> vm_args.version = JNI_VERSION_1_2;
>
> /* Create the Java Virtual Machine. */
> printf("%s:%i\n", __FILE__, __LINE__);
> jni_error = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args);
> if (jni_error < 0) {
> printf(
> "ERROR: Unable to create Java Virtual Machine, (%i)\n",
> (int) jni_error
> );
> return(EXIT_FAILURE);
> }
>
> printf("%s:%i\n", __FILE__, __LINE__);
> if ((*env)->ExceptionOccurred(env)) {
> printf("exception occurred %s:%i\
> n", __FILE__, __LINE__);
> }
>
>
> printf("%s:%i\n", __FILE__, __LINE__);
> (*jvm)->DestroyJavaVM(jvm);
>
> printf("%s:%i\n", __FILE__, __LINE__);
> argc = argc;
> argv = argv;
> return(EXIT_SUCCESS);
> }
>
>
>
> $ valgrind vg_cni
> ==5831== Memcheck, a memory error detector for x86-linux.
> ==5831== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward.
> ==5831== Using valgrind-2.1.1, a program supervision framework for
> x86-linux.
> ==5831== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.
> ==5831== For more details, rerun with: -v
> ==5831==
> vg_cni.cc:14
> ==5831== Syscall param sigaction(act) contains uninitialised or
> unaddressable byte(s)
> ==5831== at 0x3CA36025: __libc_sigaction (in /lib/tls/libc-2.3.2.so)
> ==5831== Address 0x4FFFE830 is on thread 1's stack
> ==5831==
> ==5831== Syscall param sigaction(act) contains uninitialised or
> unaddressable byte(s)
> ==5831== at 0x3CA36025: __libc_sigaction (in /lib/tls/libc-2.3.2.so)
> ==5831== by 0x7FFFFFFB: ???
> ==5831== Address 0x4FFFE780 is on thread 1's stack
> ==5831==
> ==5831== Conditional jump or move depends on uninitialised value(s)
> ==5831== at 0x3C646535: GC_push_all_eager (in /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C6478C9: GC_push_current_stack (in
> /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C64E12D: GC_generic_push_regs (in
> /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C6479FD: GC_push_roots (in /usr/lib/libgcj.so.5.0.0)
> ==5831==
> ==5831== Conditional jump or move depends on uninitialised value(s)
> ==5831== at 0x3C64653A: GC_push_all_eager (in /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C6478C9: GC_push_current_stack (in
> /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C64E12D: GC_generic_push_regs (in
> /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C6479FD: GC_push_roots (in /usr/lib/libgcj.so.5.0.0)
> ==5831==
> ==5831== Conditional jump or move depends on uninitialised value(s)
> ==5831== at 0x3C646535: GC_push_all_eager (in /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C6465B9: GC_push_all_stack (in /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C64DB96: GC_push_all_stacks (in
> /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C649815: GC_default_push_other_roots (in
> /usr/lib/libgcj.so.5.0.0)
> ==5831==
> ==5831== Syscall param sigaction(act) contains uninitialised or
> unaddressable byte(s)
> ==5831== at 0x3CAE551D: syscall (in /lib/tls/libc-2.3.2.so)
> ==5831== by 0x8048736: JvCreateJavaVM(void*) (in
> /home/tom/tmp/valgrind_gcj/vg_cni)
> ==5831== by 0x8048670: main (in /home/tom/tmp/valgrind_gcj/vg_cni)
> ==5831== Address 0x4FFFE9B0 is on thread 1's stack
> ==5831==
> ==5831== Conditional jump or move depends on uninitialised value(s)
> ==5831== at 0x3C64D25C: GC_pthread_create (in /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C472162: _Jv_ThreadStart(java::lang::Thread*,
> _Jv_Thread_t*, void (*)(java::lang::Thread*)) (in
> /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C49E6A6: java::lang::Thread::start() (in
> /usr/lib/libgcj.so.5.0.0)
> ==5831== by 0x3C473E09: _Jv_CreateJavaVM(void*) (in
> /usr/lib/libgcj.so.5.0.0)==5831==
> ==5831== Thread 2:
> ==5831== Conditional jump or move depends on uninitialised value(s)
> ==5831== at 0x3CB4CFF1: thread_wrapper (vg_libpthread.c:824)
> ==5831== by 0xB800FACC: do__quit (vg_scheduler.c:1792)
> ==5831==
> ==5831== Thread 2:
> ==5831== thread_wrapper: invalid attr->__detachstate
> ==5831== at 0x3CB4C00F: pthread_error (vg_libpthread.c:355)
> ==5831== by 0x3CB4D000: thread_wrapper (vg_libpthread.c:826)
> ==5831== by 0xB800FACC: do__quit (vg_scheduler.c:1792)
> ==5831==
> ==5831== Thread 2:
> ==5831== Conditional jump or move depends on uninitialised value(s)
> ==5831== at 0x3CB4D004: thread_wrapper (vg_libpthread.c:827)
> ==5831== by 0xB800FACC: do__quit (vg_scheduler.c:1792)
> ------------------------hangs here-----------------------------
>
> --
> Tom Schutter (mailto:to...@pl...)
> Platte River Associates, Inc. (http://www.platte.com)
|
|
From: Tom S. <to...@pl...> - 2004-06-18 15:40:49
|
Jeroen N. Witmond wrote: > Tom (and list), > > I am not an expert on valgrind, Java, JNI or GCJ, so I have no answers, > just a few questions and comments, inlined below. > > >>I have a mixed Java/C app that I am trying to run valgrind on. The >>object of this exercise is to find a difficult-to-reproduct crash that >>is related to JNI and garbage collection. Most of the C code is >>valgrind clean, it is when it is used from JNI that I am having problems. >> >>It is obvious to me that valgrind will not be able to run a standard >>JVM, [...] > > > Do you have any evidence to support this statement? I am able to run > `valgrind --tool=memcheck -v java` on a simple Java application that does > not use JNI, without any problems, errors or warnings. Hmmm. Every time I attempted this it failed for me. But that was with an older valgrind and java. I will try again. >>[...] so I started looking into GCJ. GCJ will generate standard object >>code that I should be able to run valgrind on. [...] > > > Correct, but there is no guarantee that running this compiled version of > your application will fail in the same way, or even fail at all. The way > the JVM and GCJ implement garbage collection probably is not identical. No guarantee, but it might. My standard rule now for strange and difficult bugs is to run valgrind first before trying anything else. 9 times out of 10 I beleive that it takes less time to find the cause of the bug with valgrind than with any other method. -- Tom Schutter (mailto:to...@pl...) Platte River Associates, Inc. (http://www.platte.com) |
|
From: Jeroen N. W. <jn...@xs...> - 2004-06-18 21:40:57
|
> I have two easy test cases that follow. Both generated executables that > run, but when run under valgrind, they hang (using 100% cpu) when > initializing the Java runtime. > > /* vg_cni.cc > * compile with: > * gcc-3.4 vg_cni.cc -o vg_cni -lgcj > */ FWIW, I have compiled and run your program, and it fails in the same way (using all available CPU without producing output). When I kill the program with signal 15, I get (among other stuff) the following output: ==3995== Process terminating with default action of signal 15 (SIGTERM) ==3995== at 0x408FD810: pthread_cond_wait@@GLIBC_2.3.2 (in /lib/i686/libc-2.3.2.so) ==3995== by 0x4058EC97: GC_pthread_create (in /usr/lib/libgcj.so.3.0.0) ==3995== by 0x405870A9: _Jv_ThreadStart(java::lang::Thread*, _Jv_Thread_t*, void (*)(java::lang::Thread*)) (in /usr/lib/libgcj.so.3.0.0) ==3995== by 0x40464CE0: java::lang::Thread::start() (in /usr/lib/libgcj.so.3.0.0) ==3995== I would guess this means that the gcj runtime somehow bypasses valgrind's thread handling, but I'm no expert. When I compile and link my simple java application with gcj, and valgrind the resuling executable, I get the following warnings: ==4007== warning: Valgrind's pthread_attr_setschedparam does nothing ==4007== (scheduling not changeable) ==4007== your program may misbehave as a result ==4007== warning: Valgrind's sem_destroy is incomplete ==4007== (it always succeeds, even if semaphore waited on) ==4007== your program may misbehave as a result ==4007== warning: Valgrind's pthread_attr_destroy does nothing ==4007== your program may misbehave as a result After that, the application runs and terminates normally. In both cases, I also get the warnings about "Conditional jump or move depends on uninitialised value(s)" and "Syscall param sigaction(act) contains uninitialised or unaddressable byte(s)". I am running RedHat9 (Linux BahcoBak 2.4.20-31.9 #1 Tue Apr 13 18:04:23 EDT 2004 i686 i686 i386 GNU/Linux) and gcc/gcj version 3.2.2 20030222 (Red Hat Linux 3.2.2-5). Hope this helps, Jeroen. |
|
From: Tom S. <to...@pl...> - 2004-06-18 22:12:34
|
Jeroen N. Witmond wrote: >>I have two easy test cases that follow. Both generated executables that >>run, but when run under valgrind, they hang (using 100% cpu) when >>initializing the Java runtime. >> >>/* vg_cni.cc >> * compile with: >> * gcc-3.4 vg_cni.cc -o vg_cni -lgcj >> */ > > > FWIW, I have compiled and run your program, and it fails in the same way > (using all available CPU without producing output). When I kill the > program with signal 15, I get (among other stuff) the following output: > > ==3995== Process terminating with default action of signal 15 (SIGTERM) > ==3995== at 0x408FD810: pthread_cond_wait@@GLIBC_2.3.2 (in > /lib/i686/libc-2.3.2.so) > ==3995== by 0x4058EC97: GC_pthread_create (in /usr/lib/libgcj.so.3.0.0) > ==3995== by 0x405870A9: _Jv_ThreadStart(java::lang::Thread*, > _Jv_Thread_t*, void (*)(java::lang::Thread*)) (in > /usr/lib/libgcj.so.3.0.0) > ==3995== by 0x40464CE0: java::lang::Thread::start() (in > /usr/lib/libgcj.so.3.0.0) > ==3995== > > I would guess this means that the gcj runtime somehow bypasses valgrind's > thread handling, but I'm no expert. > > When I compile and link my simple java application with gcj, and valgrind > the resuling executable, I get the following warnings: > > ==4007== warning: Valgrind's pthread_attr_setschedparam does nothing > ==4007== (scheduling not changeable) > ==4007== your program may misbehave as a result > ==4007== warning: Valgrind's sem_destroy is incomplete > ==4007== (it always succeeds, even if semaphore waited on) > ==4007== your program may misbehave as a result > ==4007== warning: Valgrind's pthread_attr_destroy does nothing > ==4007== your program may misbehave as a result > > After that, the application runs and terminates normally. > > In both cases, I also get the warnings about "Conditional jump or move > depends on uninitialised value(s)" and "Syscall param sigaction(act) > contains uninitialised or unaddressable byte(s)". > > I am running RedHat9 (Linux BahcoBak 2.4.20-31.9 #1 Tue Apr 13 18:04:23 > EDT 2004 i686 i686 i386 GNU/Linux) and gcc/gcj version 3.2.2 20030222 (Red > Hat Linux 3.2.2-5). > > Hope this helps, > > Jeroen. So what is the difference between your "simple java application" and the code I posted? -- Tom Schutter (mailto:to...@pl...) Platte River Associates, Inc. (http://www.platte.com) |
|
From: Jeroen N. W. <jn...@xs...> - 2004-06-19 06:33:31
|
> So what is the difference between your "simple java application" and the > code I posted? I'm not sure I understand your question, because the difference obviously is that my java application is written in Java (and compiled with gcj) whereas your code is written in C (and compiled with gcc). Jeroen. |