-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
1.2.2
-
sparc
-
solaris_2.6
ldd -d libTestJNI.so
mv libTestJNI.so libtest2std.so
This should produce all the 4 required shared libraries.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
To run
after setting LD_LIBARAY_PATH to the directory containing the shared libraries
The first one just works fine (the shared libraries are without the std library)
%java TestDLL.java
With our class loader getting to handle it first
>>>>>> Load class : TestJNI
>>>>>> Fetching the implementation of TestJNI
>>>>>> Load class : java.lang.Object
>>>>>> Fetching the implementation of java.lang.Object
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : TestJNIIF
>>>>>> Fetching the implementation of TestJNIIF
>>>>>> returning system class (in CLASSPATH).
>>>>>> Returning newly loaded class.
Loaded class:class TestJNI
Loaded class name:TestJNI
>>>>>> Load class : java.lang.String
>>>>>> Fetching the implementation of java.lang.String
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.System
>>>>>> Fetching the implementation of java.lang.System
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.StringBuffer
>>>>>> Fetching the implementation of java.lang.StringBuffer
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.io.PrintStream
>>>>>> Fetching the implementation of java.io.PrintStream
>>>>>> returning system class (in CLASSPATH).
JAVA: Loading test1
Called load of test1
JAVA: Loaded test1
Called method JNICall1 of test1
Called method of test1
Called method of test1
Called method of test1
>>>>>> Load class : TestJNI
>>>>>> Fetching the implementation of TestJNI
>>>>>> Load class : java.lang.Object
>>>>>> Fetching the implementation of java.lang.Object
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : TestJNIIF
>>>>>> Fetching the implementation of TestJNIIF
>>>>>> returning system class (in CLASSPATH).
>>>>>> Returning newly loaded class.
>>>>>> Load class : java.lang.String
>>>>>> Fetching the implementation of java.lang.String
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.System
>>>>>> Fetching the implementation of java.lang.System
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.StringBuffer
>>>>>> Fetching the implementation of java.lang.StringBuffer
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.io.PrintStream
>>>>>> Fetching the implementation of java.io.PrintStream
>>>>>> returning system class (in CLASSPATH).
JAVA: Loading test2
Called load of test2
JAVA: Loaded test2
Called method of test2
Called method of test2
Called method of test2
Called method of test1
Called method of test1
Called method of test1
Called method of test2
Called method of test2
Called method of test2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
This is one with the std library which fails
%java TestDLLSTDD
With our class loader getting to handle it first
>>>>>> Load class : TestJNI
>>>>>> Fetching the implementation of TestJNI
>>>>>> Load class : java.lang.Object
>>>>>> Fetching the implementation of java.lang.Object
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : TestJNIIF
>>>>>> Fetching the implementation of TestJNIIF
>>>>>> returning system class (in CLASSPATH).
>>>>>> Returning newly loaded class.
Loaded class:class TestJNI
Loaded class name:TestJNI
>>>>>> Load class : java.lang.String
>>>>>> Fetching the implementation of java.lang.String
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.System
>>>>>> Fetching the implementation of java.lang.System
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.StringBuffer
>>>>>> Fetching the implementation of java.lang.StringBuffer
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.io.PrintStream
>>>>>> Fetching the implementation of java.io.PrintStream
>>>>>> returning system class (in CLASSPATH).
JAVA: Loading test1std
Called load of test1
JAVA: Loaded test1std
Called method JNICall1 of test1
Called method of test1
Called method of test1
Called method of test1
>>>>>> Load class : TestJNI
>>>>>> Fetching the implementation of TestJNI
>>>>>> Load class : java.lang.Object
>>>>>> Fetching the implementation of java.lang.Object
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : TestJNIIF
>>>>>> Fetching the implementation of TestJNIIF
>>>>>> returning system class (in CLASSPATH).
>>>>>> Returning newly loaded class.
>>>>>> Load class : java.lang.String
>>>>>> Fetching the implementation of java.lang.String
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.System
>>>>>> Fetching the implementation of java.lang.System
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.StringBuffer
>>>>>> Fetching the implementation of java.lang.StringBuffer
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.io.PrintStream
>>>>>> Fetching the implementation of java.io.PrintStream
>>>>>> returning system class (in CLASSPATH).
JAVA: Loading test2std
SIGSEGV 11 segmentation violation
si_signo [11]: SEGV
si_errno [0]:
si_code [1]: SEGV_MAPERR [addr: 0x0]
stackpointer=EFFFE280
"Finalizer" (TID:0x154610, sys_thread_t:0x154548, state:CW, thread_t: t@6, threa
dID:0xef0c1dd8, stack_bottom:0xef0c2000, stack_size:0x20000) prio=8
[1] java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:146)
[2] java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:168)
[3] java.lang.ref.Finalizer$FinalizerWorker$FinalizerThread.run(Finalizer.java:1
24)
-------------------
"Reference Handler" (TID:0x1502a0, sys_thread_t:0x1501d8, state:CW, thread_t: t@
5, threadID:0xef101dd8, stack_bottom:0xef102000, stack_size:0x20000) prio=10
[1] java.lang.Object.wait(Object.java:424)
[2] java.lang.ref.Reference$ReferenceHandler.run(Reference.java:130)
-------------------
"Signal dispatcher" (TID:0x12c5f0, sys_thread_t:0x12c528, state:MW, thread_t: t@
4, threadID:0xef141dd8, stack_bottom:0xef142000, stack_size:0x20000) prio=10
-------------------
"main" (TID:0x38660, sys_thread_t:0x38598, state:R, thread_t: t@1, threadID:0x25
118, stack_bottom:0xf0000000, stack_size:0x20000) prio=5 *current thread*
[1] java.lang.ClassLoader$NativeLibrary.load(Native Method)
[2] java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1305)
[3] java.lang.ClassLoader.loadLibrary(ClassLoader.java:1259)
[4] java.lang.Runtime.loadLibrary0(Runtime.java:470)
[5] java.lang.System.loadLibrary(System.java:778)
[6] TestJNI.initJNI(TestJNI.java:16)
[7] java.lang.reflect.Method.invoke(Native Method)
[8] TestDLLSTD.main(TestDLLSTD.java:41)
-------------------
Abort(coredump)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
(Review ID: 104150)
======================================================================
Name: skT45625 Date: 04/26/2000
java version "1.2.2"
Solaris VM (build Solaris_JDK_1.2.2_05a, native threads, sunwjit)
I have a setup wherein I need to load multiple shared libraries implementing the
same JNI interface. To ensure that these can be resolved correctly I load them
the dlls through different class loaders. This problem occurs only when I use
the std library of the Sun Workshop C++ compiler version 5.0. If I remove the
use of cout in my code and not use std library, it just works fine.
I am attaching the setup to reproduce the problem. I have two java classes with
mains TestDLL (which does not use std library) and TestDLLSTD (which calls the
shared library using std). My class loader is MyClassesFirstClassLoader which
when loading a class checks if a .impl file is availbale. If it is available it
loads the same else returns a system loaded class (default class loader).
TestDLL/ TestDLLSTD loads the class TestJNI which implements TestJNIIF through a
class loader MyClassesFirstClassLoader. TestJNI is the class which actually make
s a call to System.loadLibrary. The native methods are defined as part of
TestJNI.java
The shared libraries are libtest1.so, libtest2.so, libtest1std.so and
libtest2std.so.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestDLL.java
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
import java.lang.reflect.*;
public class TestDLL {
public static void main(String argv [] ) {
ClassLoader loader1,loader2;
Class clazz1,clazz2;
Method method;
Object jniObject1,jniObject2;
try {
TestJNI testJNI;
System.out.println("With our class loader getting to handle it first");
loader1 = new MyClassesFirstClassLoader();
clazz1 = loader1.loadClass("TestJNI");
jniObject1 = clazz1.newInstance();
System.out.println("Loaded class:"+jniObject1.getClass());
System.out.println("Loaded class name:"+
jniObject1.getClass().getName());
Class[] pars1 = {Class.forName("java.lang.String")};
method = clazz1.getMethod("initJNI",pars1);
Object[] objs1 = {"test1"};method.invoke(jniObject1,objs1);
Class[] pars90 = {Class.forName("java.lang.String")};
method = clazz1.getMethod("JNICall1",pars90);
Object[] objs90 = {"HHello"};method.invoke(jniObject1,objs90);
Class[] pars20 = {};method = clazz1.getMethod("JNICall",pars20);
Object[] objs20 = {};method.invoke(jniObject1,objs20);
Object[] objs21 = {};method.invoke(jniObject1,objs21);
Object[] objs22 = {};method.invoke(jniObject1,objs22);
loader2 = new MyClassesFirstClassLoader();
clazz2 = loader2.loadClass("TestJNI");
jniObject2 = clazz2.newInstance();
Class[] pars30 = {Class.forName("java.lang.String")};
method = clazz2.getMethod("initJNI",pars30);
Object[] objs3 = {"test2"};method.invoke(jniObject2,objs3);
Class[] pars40 = {};method = clazz2.getMethod("JNICall",pars40);
Object[] objs40 = {};method.invoke(jniObject2,objs40);
Object[] objs41 = {};method.invoke(jniObject2,objs41);
Object[] objs41 = {};method.invoke(jniObject2,objs41);
Object[] objs42 = {};method.invoke(jniObject2,objs42);
Class[] pars21 = {};method = jniObject1.getClass().getMethod("JNICall",
pars21);
Object[] objs23 = {};method.invoke(jniObject1,objs23);
Object[] objs24 = {};method.invoke(jniObject1,objs24);
Object[] objs25 = {};method.invoke(jniObject1,objs25);
Class[] pars41 = {};method = jniObject2.getClass().getMethod("JNICall",
pars41);
Object[] objs43 = {};method.invoke(jniObject2,objs43);
Object[] objs44 = {};method.invoke(jniObject2,objs44);
Object[] objs45 = {};method.invoke(jniObject2,objs45);
} catch (Exception e) {
e.printStackTrace();
}
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestDLLSTD.java
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
import java.lang.reflect.*;
public class TestDLLSTD {
public static void main(String argv [] ) {
ClassLoader loader1,loader2;
Class clazz1,clazz2;
Method method;
Object jniObject1,jniObject2;
try {
TestJNI testJNI;
System.out.println("With our class loader getting to handle it first");
loader1 = new MyClassesFirstClassLoader();
clazz1 = loader1.loadClass("TestJNI");
jniObject1 = clazz1.newInstance();
System.out.println("Loaded class:"+jniObject1.getClass());
System.out.println("Loaded class name:"+
jniObject1.getClass().getName());
Class[] pars1 = {Class.forName("java.lang.String")};
method = clazz1.getMethod("initJNI",pars1);
Object[] objs1 = {"test1std"};method.invoke(jniObject1,objs1);
Class[] pars90 = {Class.forName("java.lang.String")};
method = clazz1.getMethod("JNICall1",pars90);
Object[] objs90 = {"HHello"};method.invoke(jniObject1,objs90);
Class[] pars20 = {};method = clazz1.getMethod("JNICall",pars20);
Object[] objs20 = {};method.invoke(jniObject1,objs20);
Object[] objs21 = {};method.invoke(jniObject1,objs21);
Object[] objs22 = {};method.invoke(jniObject1,objs22);
loader2 = new MyClassesFirstClassLoader();
clazz2 = loader2.loadClass("TestJNI");
jniObject2 = clazz2.newInstance();
Class[] pars30 = {Class.forName("java.lang.String")};
method = clazz2.getMethod("initJNI",pars30);
Object[] objs3 = {"test2std"};method.invoke(jniObject2,objs3);
Class[] pars40 = {};method = clazz2.getMethod("JNICall",pars40);
Object[] objs40 = {};method.invoke(jniObject2,objs40);
Object[] objs41 = {};method.invoke(jniObject2,objs41);
Object[] objs42 = {};method.invoke(jniObject2,objs42);
Class[] pars21 = {};method = jniObject1.getClass().getMethod("JNICall",
pars21);
Object[] objs23 = {};method.invoke(jniObject1,objs23);
Object[] objs24 = {};method.invoke(jniObject1,objs24);
Object[] objs25 = {};method.invoke(jniObject1,objs25);
Class[] pars41 = {};method = jniObject2.getClass().getMethod("JNICall",
pars41);
Object[] objs43 = {};method.invoke(jniObject2,objs43);
Object[] objs44 = {};method.invoke(jniObject2,objs44);
Object[] objs45 = {};method.invoke(jniObject2,objs45);
} catch (Exception e) {
e.printStackTrace();
}
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestJNI.java which loads the shared library
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
public class TestJNI implements TestJNIIF {
public native void JNICall();
public native void JNICall1(String str);
public void JNICallIF() {
System.out.println("JAVA: Invoking JNICall");
JNICall();
}
public TestJNI() { }
public void initJNI(java.lang.String str) {
System.out.println("JAVA: Loading "+str);
System.loadLibrary(str);
System.out.println("JAVA: Loaded "+str);
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestJNIIF.java
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
public interface TestJNIIF {
public void JNICallIF();
public void initJNI(java.lang.String str);
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for MyClassesFirstClassLoader.java
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
* MyClassesFirstClassLoader.java - a bare bones class loader.
*
* Copyright (c) 1996 Chuck McManis, All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
* CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
* SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT
* OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
import java.util.Hashtable;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
public class MyClassesFirstClassLoader extends ClassLoader {
static boolean debug = false;
private Hashtable classes = new Hashtable();
public MyClassesFirstClassLoader() {
}
/**
* This sample function for reading class implementations reads
* them from the local file system
*/
private byte getClassImplFromDataBase(String className)[] {
if (debug)
System.out.println(">>>>>> Fetching the implementation of
"+className);
byte result[];
try {
FileInputStream fi = new FileInputStream(className+".impl");
result = new byte[fi.available()];
fi.read(result);
return result;
} catch (Exception e) {
// If we caught an exception, either the class wasnt found or it
// was unreadable by our process.
return null;
}
}
/**
* This is a simple version for external clients since they
* will always want the class resolved before it is returned
* to them.
*/
public Class loadClass(String className) throws ClassNotFoundException {
return (loadClass(className, true));
}
/**
* This is the required version of loadClass which is called
* both from loadClass above and from the internal function
* FindClassFromClass.
*/
public synchronized Class loadClass(String className, boolean resolveIt)
throws ClassNotFoundException {
Class result;
byte classData[];
if (debug)
System.out.println(">>>>>> Load class : "+className);
try {
/* Check our local cache of classes */
result = (Class)classes.get(className);
if (result != null) {
if (debug)
System.out.println(">>>>>> returning cached result.");
return result;
}
/* Try to load it from our repository */
classData = getClassImplFromDataBase(className);
if (classData == null) {
throw new ClassNotFoundException();
}
/* Define it (parse the class file) */
result = defineClass("TestJNI",classData, 0, classData.length);
if (result == null) {
throw new ClassFormatError();
}
if (resolveIt) {
resolveClass(result);
}
classes.put(className, result);
if (debug)
System.out.println(">>>>>> Returning newly loaded class.");
return result;
} catch (Exception ex) {
// Check with the primordial class loader
try {
result = super.findSystemClass(className);
if (debug)
System.out.println(">>>>>> returning system class (in
CLASSPATH).");
return result;
} catch (ClassNotFoundException e) {
if (debug)
System.out.println(">>>>>> Not a system class.");
}
}
return null;
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestJNI.h
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestJNI */
#ifndef _Included_TestJNI
#define _Included_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestJNI
* Method: JNICall
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestJNI_JNICall
(JNIEnv *, jobject);
/*
* Class: TestJNI
* Method: JNICall1
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_TestJNI_JNICall1
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestJNI.cpp
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#include <jni.h>
#include <iostream>
#include <string>
#include "TestJNI.h"
#ifdef TEST1
#ifdef STD
std::string identifier = "test1";
#else
char* identifier = "test1";
#endif
#else
#ifdef STD
std::string identifier = "test2";
#else
char* identifier = "test2";
#endif
#endif
/* Defined by native libraries. */
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void *reserved) {
#ifdef STD
std::cout << "Called load of " << identifier << std::endl;
#else
printf("Called load of %s\n",identifier);
#endif
return 0x00010002;
}
JNIEXPORT void JNICALL Java_TestJNI_JNICall
(JNIEnv *, jobject) {
#ifdef STD
std::cout << "Called method of " << identifier << std::endl;
#else
printf("Called method of %s\n",identifier);
#endif
}
JNIEXPORT void JNICALL Java_TestJNI_JNICall1
(JNIEnv *, jobject, jstring) {
#ifdef STD
std::cout << "Called method JNICall1 of " << identifier << std::endl;
#else
printf("Called method JNICall1 of %s\n",identifier);
#endif
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
The Makefile
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#the path to the C++ compiler Version 5.0
#CC = /export/home/SUNWspro/SC5.0/bin/CC
CC = /opt/SUNWspro/SC5.0/bin/CC
#the standard include
STDINCLUDE = /opt/SUNWspro/SC5.0/include/CC
#include
JDKINCLUDE = /opt/Java1.2.2_05a/Solaris_JDK_1.2.2_05a/include
INCLUDES = -I./ -I$(STDINCLUDE) -I$(JDKINCLUDE) -I$(JDKINCLUDE)/solaris
LIBS = -lxnet -lCrun -lcopt
#compilation flags
CFLAGS = $(INCLUDES)
TestJNI:
$(CC) -G $(CFLAGS) -DTEST1 -o lib$@.so $@.cpp $(LIBS)
ldd -d libTestJNI.so
mv libTestJNI.so libtest1.so
$(CC) -G $(CFLAGS) -DTEST2 -o lib$@.so $@.cpp $(LIBS)
ldd -d libTestJNI.so
mv libTestJNI.so libtest2.so
$(CC) -G $(CFLAGS) -DTEST1 -DSTD -o lib$@.so $@.cpp $(LIBS) -lCstd
ldd -d libTestJNI.so
mv libTestJNI.so libtest1std.so
$(CC) -G $(CFLAGS) -DTEST2 -DSTD -o lib$@.so $@.cpp $(LIBS) -lCstd
mv libTestJNI.so libtest2std.so
This should produce all the 4 required shared libraries.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
To run
after setting LD_LIBARAY_PATH to the directory containing the shared libraries
The first one just works fine (the shared libraries are without the std library)
%java TestDLL.java
With our class loader getting to handle it first
>>>>>> Load class : TestJNI
>>>>>> Fetching the implementation of TestJNI
>>>>>> Load class : java.lang.Object
>>>>>> Fetching the implementation of java.lang.Object
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : TestJNIIF
>>>>>> Fetching the implementation of TestJNIIF
>>>>>> returning system class (in CLASSPATH).
>>>>>> Returning newly loaded class.
Loaded class:class TestJNI
Loaded class name:TestJNI
>>>>>> Load class : java.lang.String
>>>>>> Fetching the implementation of java.lang.String
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.System
>>>>>> Fetching the implementation of java.lang.System
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.StringBuffer
>>>>>> Fetching the implementation of java.lang.StringBuffer
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.io.PrintStream
>>>>>> Fetching the implementation of java.io.PrintStream
>>>>>> returning system class (in CLASSPATH).
JAVA: Loading test1
Called load of test1
JAVA: Loaded test1
Called method JNICall1 of test1
Called method of test1
Called method of test1
Called method of test1
>>>>>> Load class : TestJNI
>>>>>> Fetching the implementation of TestJNI
>>>>>> Load class : java.lang.Object
>>>>>> Fetching the implementation of java.lang.Object
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : TestJNIIF
>>>>>> Fetching the implementation of TestJNIIF
>>>>>> returning system class (in CLASSPATH).
>>>>>> Returning newly loaded class.
>>>>>> Load class : java.lang.String
>>>>>> Fetching the implementation of java.lang.String
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.System
>>>>>> Fetching the implementation of java.lang.System
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.StringBuffer
>>>>>> Fetching the implementation of java.lang.StringBuffer
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.io.PrintStream
>>>>>> Fetching the implementation of java.io.PrintStream
>>>>>> returning system class (in CLASSPATH).
JAVA: Loading test2
Called load of test2
JAVA: Loaded test2
Called method of test2
Called method of test2
Called method of test2
Called method of test1
Called method of test1
Called method of test1
Called method of test2
Called method of test2
Called method of test2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
This is one with the std library which fails
%java TestDLLSTDD
With our class loader getting to handle it first
>>>>>> Load class : TestJNI
>>>>>> Fetching the implementation of TestJNI
>>>>>> Load class : java.lang.Object
>>>>>> Fetching the implementation of java.lang.Object
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : TestJNIIF
>>>>>> Fetching the implementation of TestJNIIF
>>>>>> returning system class (in CLASSPATH).
>>>>>> Returning newly loaded class.
Loaded class:class TestJNI
Loaded class name:TestJNI
>>>>>> Load class : java.lang.String
>>>>>> Fetching the implementation of java.lang.String
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.System
>>>>>> Fetching the implementation of java.lang.System
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.StringBuffer
>>>>>> Fetching the implementation of java.lang.StringBuffer
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.io.PrintStream
>>>>>> Fetching the implementation of java.io.PrintStream
>>>>>> returning system class (in CLASSPATH).
JAVA: Loading test1std
Called load of test1
JAVA: Loaded test1std
Called method JNICall1 of test1
Called method of test1
Called method of test1
Called method of test1
>>>>>> Load class : TestJNI
>>>>>> Fetching the implementation of TestJNI
>>>>>> Load class : java.lang.Object
>>>>>> Fetching the implementation of java.lang.Object
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : TestJNIIF
>>>>>> Fetching the implementation of TestJNIIF
>>>>>> returning system class (in CLASSPATH).
>>>>>> Returning newly loaded class.
>>>>>> Load class : java.lang.String
>>>>>> Fetching the implementation of java.lang.String
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.System
>>>>>> Fetching the implementation of java.lang.System
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.lang.StringBuffer
>>>>>> Fetching the implementation of java.lang.StringBuffer
>>>>>> returning system class (in CLASSPATH).
>>>>>> Load class : java.io.PrintStream
>>>>>> Fetching the implementation of java.io.PrintStream
>>>>>> returning system class (in CLASSPATH).
JAVA: Loading test2std
SIGSEGV 11 segmentation violation
si_signo [11]: SEGV
si_errno [0]:
si_code [1]: SEGV_MAPERR [addr: 0x0]
stackpointer=EFFFE280
"Finalizer" (TID:0x154610, sys_thread_t:0x154548, state:CW, thread_t: t@6, threa
dID:0xef0c1dd8, stack_bottom:0xef0c2000, stack_size:0x20000) prio=8
[1] java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:146)
[2] java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:168)
[3] java.lang.ref.Finalizer$FinalizerWorker$FinalizerThread.run(Finalizer.java:1
24)
-------------------
"Reference Handler" (TID:0x1502a0, sys_thread_t:0x1501d8, state:CW, thread_t: t@
5, threadID:0xef101dd8, stack_bottom:0xef102000, stack_size:0x20000) prio=10
[1] java.lang.Object.wait(Object.java:424)
[2] java.lang.ref.Reference$ReferenceHandler.run(Reference.java:130)
-------------------
"Signal dispatcher" (TID:0x12c5f0, sys_thread_t:0x12c528, state:MW, thread_t: t@
4, threadID:0xef141dd8, stack_bottom:0xef142000, stack_size:0x20000) prio=10
-------------------
"main" (TID:0x38660, sys_thread_t:0x38598, state:R, thread_t: t@1, threadID:0x25
118, stack_bottom:0xf0000000, stack_size:0x20000) prio=5 *current thread*
[1] java.lang.ClassLoader$NativeLibrary.load(Native Method)
[2] java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1305)
[3] java.lang.ClassLoader.loadLibrary(ClassLoader.java:1259)
[4] java.lang.Runtime.loadLibrary0(Runtime.java:470)
[5] java.lang.System.loadLibrary(System.java:778)
[6] TestJNI.initJNI(TestJNI.java:16)
[7] java.lang.reflect.Method.invoke(Native Method)
[8] TestDLLSTD.main(TestDLLSTD.java:41)
-------------------
Abort(coredump)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
(Review ID: 104150)
======================================================================
Name: skT45625 Date: 04/26/2000
java version "1.2.2"
Solaris VM (build Solaris_JDK_1.2.2_05a, native threads, sunwjit)
I have a setup wherein I need to load multiple shared libraries implementing the
same JNI interface. To ensure that these can be resolved correctly I load them
the dlls through different class loaders. This problem occurs only when I use
the std library of the Sun Workshop C++ compiler version 5.0. If I remove the
use of cout in my code and not use std library, it just works fine.
I am attaching the setup to reproduce the problem. I have two java classes with
mains TestDLL (which does not use std library) and TestDLLSTD (which calls the
shared library using std). My class loader is MyClassesFirstClassLoader which
when loading a class checks if a .impl file is availbale. If it is available it
loads the same else returns a system loaded class (default class loader).
TestDLL/ TestDLLSTD loads the class TestJNI which implements TestJNIIF through a
class loader MyClassesFirstClassLoader. TestJNI is the class which actually make
s a call to System.loadLibrary. The native methods are defined as part of
TestJNI.java
The shared libraries are libtest1.so, libtest2.so, libtest1std.so and
libtest2std.so.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestDLL.java
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
import java.lang.reflect.*;
public class TestDLL {
public static void main(String argv [] ) {
ClassLoader loader1,loader2;
Class clazz1,clazz2;
Method method;
Object jniObject1,jniObject2;
try {
TestJNI testJNI;
System.out.println("With our class loader getting to handle it first");
loader1 = new MyClassesFirstClassLoader();
clazz1 = loader1.loadClass("TestJNI");
jniObject1 = clazz1.newInstance();
System.out.println("Loaded class:"+jniObject1.getClass());
System.out.println("Loaded class name:"+
jniObject1.getClass().getName());
Class[] pars1 = {Class.forName("java.lang.String")};
method = clazz1.getMethod("initJNI",pars1);
Object[] objs1 = {"test1"};method.invoke(jniObject1,objs1);
Class[] pars90 = {Class.forName("java.lang.String")};
method = clazz1.getMethod("JNICall1",pars90);
Object[] objs90 = {"HHello"};method.invoke(jniObject1,objs90);
Class[] pars20 = {};method = clazz1.getMethod("JNICall",pars20);
Object[] objs20 = {};method.invoke(jniObject1,objs20);
Object[] objs21 = {};method.invoke(jniObject1,objs21);
Object[] objs22 = {};method.invoke(jniObject1,objs22);
loader2 = new MyClassesFirstClassLoader();
clazz2 = loader2.loadClass("TestJNI");
jniObject2 = clazz2.newInstance();
Class[] pars30 = {Class.forName("java.lang.String")};
method = clazz2.getMethod("initJNI",pars30);
Object[] objs3 = {"test2"};method.invoke(jniObject2,objs3);
Class[] pars40 = {};method = clazz2.getMethod("JNICall",pars40);
Object[] objs40 = {};method.invoke(jniObject2,objs40);
Object[] objs41 = {};method.invoke(jniObject2,objs41);
Object[] objs41 = {};method.invoke(jniObject2,objs41);
Object[] objs42 = {};method.invoke(jniObject2,objs42);
Class[] pars21 = {};method = jniObject1.getClass().getMethod("JNICall",
pars21);
Object[] objs23 = {};method.invoke(jniObject1,objs23);
Object[] objs24 = {};method.invoke(jniObject1,objs24);
Object[] objs25 = {};method.invoke(jniObject1,objs25);
Class[] pars41 = {};method = jniObject2.getClass().getMethod("JNICall",
pars41);
Object[] objs43 = {};method.invoke(jniObject2,objs43);
Object[] objs44 = {};method.invoke(jniObject2,objs44);
Object[] objs45 = {};method.invoke(jniObject2,objs45);
} catch (Exception e) {
e.printStackTrace();
}
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestDLLSTD.java
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
import java.lang.reflect.*;
public class TestDLLSTD {
public static void main(String argv [] ) {
ClassLoader loader1,loader2;
Class clazz1,clazz2;
Method method;
Object jniObject1,jniObject2;
try {
TestJNI testJNI;
System.out.println("With our class loader getting to handle it first");
loader1 = new MyClassesFirstClassLoader();
clazz1 = loader1.loadClass("TestJNI");
jniObject1 = clazz1.newInstance();
System.out.println("Loaded class:"+jniObject1.getClass());
System.out.println("Loaded class name:"+
jniObject1.getClass().getName());
Class[] pars1 = {Class.forName("java.lang.String")};
method = clazz1.getMethod("initJNI",pars1);
Object[] objs1 = {"test1std"};method.invoke(jniObject1,objs1);
Class[] pars90 = {Class.forName("java.lang.String")};
method = clazz1.getMethod("JNICall1",pars90);
Object[] objs90 = {"HHello"};method.invoke(jniObject1,objs90);
Class[] pars20 = {};method = clazz1.getMethod("JNICall",pars20);
Object[] objs20 = {};method.invoke(jniObject1,objs20);
Object[] objs21 = {};method.invoke(jniObject1,objs21);
Object[] objs22 = {};method.invoke(jniObject1,objs22);
loader2 = new MyClassesFirstClassLoader();
clazz2 = loader2.loadClass("TestJNI");
jniObject2 = clazz2.newInstance();
Class[] pars30 = {Class.forName("java.lang.String")};
method = clazz2.getMethod("initJNI",pars30);
Object[] objs3 = {"test2std"};method.invoke(jniObject2,objs3);
Class[] pars40 = {};method = clazz2.getMethod("JNICall",pars40);
Object[] objs40 = {};method.invoke(jniObject2,objs40);
Object[] objs41 = {};method.invoke(jniObject2,objs41);
Object[] objs42 = {};method.invoke(jniObject2,objs42);
Class[] pars21 = {};method = jniObject1.getClass().getMethod("JNICall",
pars21);
Object[] objs23 = {};method.invoke(jniObject1,objs23);
Object[] objs24 = {};method.invoke(jniObject1,objs24);
Object[] objs25 = {};method.invoke(jniObject1,objs25);
Class[] pars41 = {};method = jniObject2.getClass().getMethod("JNICall",
pars41);
Object[] objs43 = {};method.invoke(jniObject2,objs43);
Object[] objs44 = {};method.invoke(jniObject2,objs44);
Object[] objs45 = {};method.invoke(jniObject2,objs45);
} catch (Exception e) {
e.printStackTrace();
}
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestJNI.java which loads the shared library
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
public class TestJNI implements TestJNIIF {
public native void JNICall();
public native void JNICall1(String str);
public void JNICallIF() {
System.out.println("JAVA: Invoking JNICall");
JNICall();
}
public TestJNI() { }
public void initJNI(java.lang.String str) {
System.out.println("JAVA: Loading "+str);
System.loadLibrary(str);
System.out.println("JAVA: Loaded "+str);
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestJNIIF.java
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
public interface TestJNIIF {
public void JNICallIF();
public void initJNI(java.lang.String str);
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for MyClassesFirstClassLoader.java
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
* MyClassesFirstClassLoader.java - a bare bones class loader.
*
* Copyright (c) 1996 Chuck McManis, All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
* CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
* SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT
* OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
import java.util.Hashtable;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
public class MyClassesFirstClassLoader extends ClassLoader {
static boolean debug = false;
private Hashtable classes = new Hashtable();
public MyClassesFirstClassLoader() {
}
/**
* This sample function for reading class implementations reads
* them from the local file system
*/
private byte getClassImplFromDataBase(String className)[] {
if (debug)
System.out.println(">>>>>> Fetching the implementation of
"+className);
byte result[];
try {
FileInputStream fi = new FileInputStream(className+".impl");
result = new byte[fi.available()];
fi.read(result);
return result;
} catch (Exception e) {
// If we caught an exception, either the class wasnt found or it
// was unreadable by our process.
return null;
}
}
/**
* This is a simple version for external clients since they
* will always want the class resolved before it is returned
* to them.
*/
public Class loadClass(String className) throws ClassNotFoundException {
return (loadClass(className, true));
}
/**
* This is the required version of loadClass which is called
* both from loadClass above and from the internal function
* FindClassFromClass.
*/
public synchronized Class loadClass(String className, boolean resolveIt)
throws ClassNotFoundException {
Class result;
byte classData[];
if (debug)
System.out.println(">>>>>> Load class : "+className);
try {
/* Check our local cache of classes */
result = (Class)classes.get(className);
if (result != null) {
if (debug)
System.out.println(">>>>>> returning cached result.");
return result;
}
/* Try to load it from our repository */
classData = getClassImplFromDataBase(className);
if (classData == null) {
throw new ClassNotFoundException();
}
/* Define it (parse the class file) */
result = defineClass("TestJNI",classData, 0, classData.length);
if (result == null) {
throw new ClassFormatError();
}
if (resolveIt) {
resolveClass(result);
}
classes.put(className, result);
if (debug)
System.out.println(">>>>>> Returning newly loaded class.");
return result;
} catch (Exception ex) {
// Check with the primordial class loader
try {
result = super.findSystemClass(className);
if (debug)
System.out.println(">>>>>> returning system class (in
CLASSPATH).");
return result;
} catch (ClassNotFoundException e) {
if (debug)
System.out.println(">>>>>> Not a system class.");
}
}
return null;
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestJNI.h
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestJNI */
#ifndef _Included_TestJNI
#define _Included_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestJNI
* Method: JNICall
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestJNI_JNICall
(JNIEnv *, jobject);
/*
* Class: TestJNI
* Method: JNICall1
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_TestJNI_JNICall1
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Code for TestJNI.cpp
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#include <jni.h>
#include <iostream>
#include <string>
#include "TestJNI.h"
#ifdef TEST1
#ifdef STD
std::string identifier = "test1";
#else
char* identifier = "test1";
#endif
#else
#ifdef STD
std::string identifier = "test2";
#else
char* identifier = "test2";
#endif
#endif
/* Defined by native libraries. */
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void *reserved) {
#ifdef STD
std::cout << "Called load of " << identifier << std::endl;
#else
printf("Called load of %s\n",identifier);
#endif
return 0x00010002;
}
JNIEXPORT void JNICALL Java_TestJNI_JNICall
(JNIEnv *, jobject) {
#ifdef STD
std::cout << "Called method of " << identifier << std::endl;
#else
printf("Called method of %s\n",identifier);
#endif
}
JNIEXPORT void JNICALL Java_TestJNI_JNICall1
(JNIEnv *, jobject, jstring) {
#ifdef STD
std::cout << "Called method JNICall1 of " << identifier << std::endl;
#else
printf("Called method JNICall1 of %s\n",identifier);
#endif
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
The Makefile
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#the path to the C++ compiler Version 5.0
#CC = /export/home/SUNWspro/SC5.0/bin/CC
CC = /opt/SUNWspro/SC5.0/bin/CC
#the standard include
STDINCLUDE = /opt/SUNWspro/SC5.0/include/CC
#include
JDKINCLUDE = /opt/Java1.2.2_05a/Solaris_JDK_1.2.2_05a/include
INCLUDES = -I./ -I$(STDINCLUDE) -I$(JDKINCLUDE) -I$(JDKINCLUDE)/solaris
LIBS = -lxnet -lCrun -lcopt
#compilation flags
CFLAGS = $(INCLUDES)
TestJNI:
$(CC) -G $(CFLAGS) -DTEST1 -o lib$@.so $@.cpp $(LIBS)
ldd -d libTestJNI.so
mv libTestJNI.so libtest1.so
$(CC) -G $(CFLAGS) -DTEST2 -o lib$@.so $@.cpp $(LIBS)
ldd -d libTestJNI.so
mv libTestJNI.so libtest2.so
$(CC) -G $(CFLAGS) -DTEST1 -DSTD -o lib$@.so $@.cpp $(LIBS) -lCstd
ldd -d libTestJNI.so
mv libTestJNI.so libtest1std.so
$(CC) -G $(CFLAGS) -DTEST2 -DSTD -o lib$@.so $@.cpp $(LIBS) -lCstd