dist: RedHat 6.1
kernel: 2.2.13
jdk: Blackdown 1.2.2RC3
glibc: 2.1.2-11
My story so far:
I use the invocation api to load the jvm and run some java code. If the
thread I use to run the code is the main thread, everything works fine.
If I create a thread (pthread_create) to run the code, I get a segv when
that thread exits. This code runs fine on every Solaris or win32 (1.1
or 1.2) jvm that I've tried. I am aware that there are problems with
using the green thread version with the invocation api, but to the best
of my knowledge I am using native threads.
To demonstrate the problem, I modified jdk1.2.2/src/launcher/java.c to
take a "-createthread" flag, which runs the java code in a new thread:
[chrisc@new-joker launcher]$ ./java Hello
Hello.
[chrisc@new-joker launcher]$ ./java -createthread Hello
Hello.
SIGSEGV 11* segmentation violation
Full thread dump Classic VM (Linux_JDK_RC3, native threads):
"Finalizer" (TID:0x2b90e320, sys_thread_t:0x80d0dc8, state:CW,
native ID:0xc04) prio=8
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:112)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:127)
at
java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:174)
"Reference Handler" (TID:0x2b90e3b0, sys_thread_t:0x80caa50,
state:CW, native ID:0x803) prio=10
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:424)
at
java.lang.ref.Reference$ReferenceHandler.run(Reference.java:114)
"SIGQUIT handler" (TID:0x2b90e3e0, sys_thread_t:0x80d0290, state:R,
native ID:0x402) prio=5
"main" (TID:0x2b90e1e0, sys_thread_t:0x80536c8, state:R, native
ID:0x400) prio=5
Monitor Cache Dump:
java.lang.ref.ReferenceQueue$Lock@2B90E338/2B944028: <unowned>
Waiting to be notified:
"Finalizer" (0x80d0dc8)
java.lang.ref.Reference$Lock@2B90E3C0/2B943B20: <unowned>
Waiting to be notified:
"Reference Handler" (0x80caa50)
Registered Monitor Dump:
PCMap lock: <unowned>
utf8 hash table: <unowned>
JNI pinning lock: <unowned>
JNI global reference lock: <unowned>
BinClass lock: <unowned>
Class linking lock: <unowned>
System class loader lock: <unowned>
Code rewrite lock: <unowned>
Heap lock: <unowned>
Monitor cache lock: <unowned>
Thread queue lock: <unowned>
Under gdb, I see that the crash is in pthread_exit in the thread which I
created that ran the java code:
(gdb) where
#0 0x8126773 in ?? ()
#1 0x2aacb6e9 in pthread_exit (retval=0x0) at join.c:35
#2 0x2aacbed0 in pthread_allocate_stack (attr=0x7f1ffe60,
default_new_thread=0x7f3ffe60, pagesize=716003008,
out_new_thread=0x0,
out_new_thread_bottom=0x0, out_guardaddr=0x1005,
out_guardsize=0x46db)
at manager.c:216
(gdb) info thr
* 6 Thread 18139 0x8126773 in ?? ()
5 Thread 18138 0x2ab6358b in __sigsuspend (set=0x7f3ff93c)
at ../sysdeps/unix/sysv/linux/sigsuspend.c:48
4 Thread 18137 0x2ab6358b in __sigsuspend (set=0x7f5ff93c)
at ../sysdeps/unix/sysv/linux/sigsuspend.c:48
3 Thread 18136 0x2ab6358b in __sigsuspend (set=0x7f7ffae0)
at ../sysdeps/unix/sysv/linux/sigsuspend.c:48
2 Thread 18134 (initial thread) 0x2ab6358b in __sigsuspend
(set=0x7ffffa14)
at ../sysdeps/unix/sysv/linux/sigsuspend.c:48
1 Thread 18135 (manager thread) 0x2abef320 in __poll (fds=0x80d3d90,
nfds=1, timeout=2000) at ../sysdeps/unix/sysv/linux/poll.c:45
To reproduce the problem:
* Extract the source from /usr/local/jdk1.2.2/src.jar using "jar xvf
src.jar"
* cd src/launcher
* Patch java.c with the included diffs.
* Compile the launcher ("java") using:
$(CC) -g -Wall -L/usr/local/jdk1.2.2/jre/lib/i386/classic
-I/usr/local/jdk1.2.2/include -I/usr/local/jdk1.2.2/include/linux
-D_GNU_SOURCE -D_REENTRANT=1 java.c java_md.c -o java -ldl -lpthread
-ljvm
(I used egcs.)
* Run as above.
Any insights/guesses/suggestions would be greatly appreciated. At this
point, I'll probably attempt to build the jdk from the source using the
Blackdown patches.
Thanks,
Chris
*** java.c Sat Jan 1 16:30:32 2000
--- javax.c Sat Jan 1 19:45:27 2000
***************
*** 29,34 ****
--- 29,35 ----
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+ #include <pthread.h>
#include <jni.h>
#include "java.h"
***************
*** 38,43 ****
--- 39,45 ----
#endif
static jboolean printVersion = JNI_FALSE;
+ static jboolean createThread = JNI_FALSE;
static char *progname;
jboolean debug = JNI_FALSE;
***************
*** 75,96 ****
/*
* Entry point.
*/
int
! main(int argc, char **argv)
{
- JavaVM *vm = 0;
JNIEnv *env = 0;
- char *jarfile = 0;
- char *classname = 0;
char *s = 0;
- jclass mainClass;
- jmethodID mainID;
- jobjectArray mainArgs;
- int ret;
InvocationFunctions ifn;
char *jvmtype = 0;
jboolean jvmspecified = JNI_FALSE; /* Assume no option
specified. */
jlong start, end;
if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
debug = JNI_TRUE;
--- 77,100 ----
/*
* Entry point.
*/
+ int argc;
+ char **argv;
+ JavaVM *vm = 0;
+ char *jarfile = 0;
+ char *classname = 0;
+
int
! initialize_vm(jboolean *prun)
{
JNIEnv *env = 0;
char *s = 0;
InvocationFunctions ifn;
char *jvmtype = 0;
jboolean jvmspecified = JNI_FALSE; /* Assume no option
specified. */
jlong start, end;
+ int ret;
+
+ *prun = JNI_FALSE;
if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
debug = JNI_TRUE;
***************
*** 110,116 ****
}
ifn.CreateJavaVM = 0; ifn.GetDefaultJavaVMInitArgs = 0;
if (!LoadJavaVM(jvmtype, &ifn))
! return 1;
/* Grab the program name */
progname = *argv++;
--- 114,120 ----
}
ifn.CreateJavaVM = 0; ifn.GetDefaultJavaVMInitArgs = 0;
if (!LoadJavaVM(jvmtype, &ifn))
! return 1;
/* Grab the program name */
progname = *argv++;
***************
*** 129,135 ****
/* Preprocess wrapper arguments */
TranslateDashJArgs(&argc, &argv);
if (!AddApplicationOptions())
! return 1;
#endif
/* Set default CLASSPATH */
--- 133,139 ----
/* Preprocess wrapper arguments */
TranslateDashJArgs(&argc, &argv);
if (!AddApplicationOptions())
! return 1;
#endif
/* Set default CLASSPATH */
***************
*** 145,151 ****
if (ifn.GetDefaultJavaVMInitArgs(&args) != JNI_OK ||
args.classpath == 0) {
fprintf(stderr, "Could not get default system class path.\n");
! return 1;
}
buf = MemAlloc(strlen(args.classpath) + strlen(s) + 2);
sprintf(buf, "%s%c%s", args.classpath, PATH_SEPARATOR, s);
--- 149,155 ----
if (ifn.GetDefaultJavaVMInitArgs(&args) != JNI_OK ||
args.classpath == 0) {
fprintf(stderr, "Could not get default system class path.\n");
! return 1;
}
buf = MemAlloc(strlen(args.classpath) + strlen(s) + 2);
sprintf(buf, "%s%c%s", args.classpath, PATH_SEPARATOR, s);
***************
*** 158,164 ****
/* Parse command line options */
if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) {
! return ret;
}
/* Override class path if -jar flag was specified */
--- 162,168 ----
/* Parse command line options */
if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) {
! return ret;
}
/* Override class path if -jar flag was specified */
***************
*** 172,195 ****
start = CounterGet();
if (!InitializeJVM(&vm, &env, &ifn)) {
fprintf(stderr, "Could not create the Java virtual machine.\n");
! return 1;
}
if (printVersion) {
PrintJavaVersion(env);
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
! ret = 1;
} else {
! ret = 0;
}
- goto leave;
}
/* If the user specified neither a class name or a JAR file */
if (jarfile == 0 && classname == 0) {
PrintUsage();
! goto leave;
}
if (debug) {
--- 176,198 ----
start = CounterGet();
if (!InitializeJVM(&vm, &env, &ifn)) {
fprintf(stderr, "Could not create the Java virtual machine.\n");
! return 1;
}
if (printVersion) {
PrintJavaVersion(env);
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
! return 1;
} else {
! return 0;
}
}
/* If the user specified neither a class name or a JAR file */
if (jarfile == 0 && classname == 0) {
PrintUsage();
! return 0;
}
if (debug) {
***************
*** 198,203 ****
--- 201,225 ----
(jint)Counter2Micros(end-start));
}
+ *prun = JNI_TRUE;
+ return 0;
+ }
+
+ void *
+ run_main(void *pret_arg)
+ {
+ int *pret = (int *)pret_arg;
+ jclass mainClass;
+ jmethodID mainID;
+ jobjectArray mainArgs;
+ JNIEnv *env = 0;
+
+ if ((*vm)->AttachCurrentThread(vm, (void **)&env, NULL) != 0) {
+ fprintf(stderr, "Could not attach thread.\n");
+ *pret = 1;
+ return NULL;
+ }
+
/* At this stage, argc/argv have the applications' arguments */
if (debug) {
int i = 0;
***************
*** 208,231 ****
}
}
- ret = 1;
-
/* Get the application's main class */
if (jarfile != 0) {
jstring mainClassName = GetMainClassName(env, jarfile);
if (mainClassName == NULL) {
fprintf(stderr, "Failed to load Main-Class manifest attribute "
"from\n%s\n", jarfile);
! goto leave;
}
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
! goto leave;
}
classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
if (classname == NULL) {
(*env)->ExceptionDescribe(env);
! goto leave;
}
mainClass = LoadClass(env, classname);
(*env)->ReleaseStringUTFChars(env, mainClassName, classname);
--- 230,254 ----
}
}
/* Get the application's main class */
if (jarfile != 0) {
jstring mainClassName = GetMainClassName(env, jarfile);
if (mainClassName == NULL) {
fprintf(stderr, "Failed to load Main-Class manifest attribute "
"from\n%s\n", jarfile);
! *pret = 1;
! return NULL;
}
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
! *pret = 1;
! return NULL;
}
classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
if (classname == NULL) {
(*env)->ExceptionDescribe(env);
! *pret = 1;
! return NULL;
}
mainClass = LoadClass(env, classname);
(*env)->ReleaseStringUTFChars(env, mainClassName, classname);
***************
*** 234,240 ****
}
if (mainClass == NULL) {
(*env)->ExceptionDescribe(env);
! goto leave;
}
/* Get the application's main method */
--- 257,264 ----
}
if (mainClass == NULL) {
(*env)->ExceptionDescribe(env);
! *pret = 1;
! return NULL;
}
/* Get the application's main method */
***************
*** 246,259 ****
} else {
fprintf(stderr, "No main method found in specified class.\n");
}
! goto leave;
}
/* Build argument array */
mainArgs = NewPlatformStringArray(env, argv, argc);
if (mainArgs == NULL) {
(*env)->ExceptionDescribe(env);
! goto leave;
}
/* Invoke main method. */
--- 270,285 ----
} else {
fprintf(stderr, "No main method found in specified class.\n");
}
! *pret = 1;
! return NULL;
}
/* Build argument array */
mainArgs = NewPlatformStringArray(env, argv, argc);
if (mainArgs == NULL) {
(*env)->ExceptionDescribe(env);
! *pret = 1;
! return NULL;
}
/* Invoke main method. */
***************
*** 265,271 ****
stack trace as ExceptionDescribe and could never actually be
overridden by application programs. */
(*env)->ExceptionDescribe(env);
! goto leave;
}
/*
--- 291,298 ----
stack trace as ExceptionDescribe and could never actually be
overridden by application programs. */
(*env)->ExceptionDescribe(env);
! *pret = 1;
! return NULL;
}
/*
***************
*** 273,286 ****
* the application's main method exits.
*/
if ((*vm)->DetachCurrentThread(vm) != 0) {
! fprintf(stderr, "Could not detach main thread.\n");
! goto leave;
}
- ret = 0;
! leave:
(*vm)->DestroyJavaVM(vm);
! return ret;
}
/*
--- 300,349 ----
* the application's main method exits.
*/
if ((*vm)->DetachCurrentThread(vm) != 0) {
! fprintf(stderr, "Could not detach thread.\n");
! *pret = 1;
! return NULL;
}
! *pret = 0;
! return NULL;
! }
!
! void
! destroy_vm(void)
! {
(*vm)->DestroyJavaVM(vm);
! }
!
! int
! main(int argc_local, char **argv_local)
! {
! pthread_t tid;
! int ret;
! jboolean run;
!
! argc = argc_local;
! argv = argv_local;
!
! if ((ret = initialize_vm(&run)) != 0)
! exit(ret);
!
! if (run) {
! if (createThread) {
! pthread_create(&tid, NULL, run_main, &ret);
! pthread_join(tid, NULL);
! } else {
! run_main(&ret);
! }
!
! if (ret != 0)
! exit(ret);
!
! destroy_vm();
! }
!
! exit(0);
! return -1;
}
/*
***************
*** 358,363 ****
--- 421,428 ----
} else if (strcmp(arg, "-version") == 0) {
printVersion = JNI_TRUE;
return JNI_TRUE;
+ } else if (strcmp(arg, "-createthread") == 0) {
+ createThread = JNI_TRUE;
} else if (strcmp(arg, "-X") == 0) {
*pret = PrintXUsage();
return JNI_FALSE;
----------------------------------------------------------------------
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]