vparot / javahidapi

Automatically exported from code.google.com/p/javahidapi
0 stars 0 forks source link

Callback Event creation uses the wrong class loader in HIDManager.cpp #4

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Create a custom "defining" class loader (I used an OSGi FW for that)
2. Create an implementation of the HIDManager and overwrite call back methods
3. Load this HIDManagerImpl with the custom ClassLoader together with all 
depending classes (like HIDDeviceInfo f.i.)
4. Call listDevices (from this class loader) -> everything works as expected
5. Un-plug/Plug-in a device -> You'll see a CNFE:

Exception in thread "Thread-4" java.lang.NoClassDefFoundError: 
com/codeminders/hidapi/HIDDeviceInfo
Caused by: java.lang.ClassNotFoundException: 
com.codeminders.hidapi.HIDDeviceInfo
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Exception in thread "Thread-6" java.lang.NoClassDefFoundError: 
com/codeminders/hidapi/HIDDeviceInfo
Caused by: java.lang.ClassNotFoundException: 
com.codeminders.hidapi.HIDDeviceInfo
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

My unqualified assumption is that you are using the system class loader and not 
the class loader of the HIDManagerImpl to load the class (which by definition 
has to have access to the class file). I guess it should be a rather simple fix 
when you know where to look for it. Unfortunately my C++ is a bit rusty. 
However, I was able to verify that the HIDManager could be loaded in the 
"hid_device_jni_callback" in HIDManager.cpp, but it fails loading the 
HIDDeviceInfo. I assume a similar approach to the "getPeer" is required here or 
the classloaders in the system have to be queried, which one is capable of 
loading the class definition... Just my 2 cents.

I was using the trunk from about Dec 20. 2011. And I am running on Mac OS X.

I hope that helps...

Original issue reported on code.google.com by mirkoj...@gmail.com on 10 Jan 2012 at 12:00

GoogleCodeExporter commented 8 years ago
Alex, could you please take a look at this. 

Original comment by kroko...@gmail.com on 10 Jan 2012 at 12:52

GoogleCodeExporter commented 8 years ago
I published my open source project, where this problem appears. Just checkout 
the sources and use a regular maven build (mvn clean install). You can run the 
project by using the /distribution/pax.assembly/target/*.zip binary after 
having build the project. Unpack the binary, and execute "bash pax-run.sh 
debug" or on windows [pax-run.bat debug] for a remote debugging session. The 
project containing the javahidapi sources is located in /drivers/hid. It 
doesn't matter what the project intends to do. As soon as you plug-in or unplug 
a hid device, you'll notice the problem immediately. I hope that helps 
pinpointing the problem. You're help is greatly appreciated!
ProjectPage: https://github.com/cibuddy/cibuddy

Original comment by mirkoj...@gmail.com on 6 Feb 2012 at 10:17

GoogleCodeExporter commented 8 years ago
When running my code with multiple USB devices, I now sometimes get the 
following output as well:

Exception in thread "Thread-24" java.lang.NoClassDefFoundError: 
com/codeminders/hidapi/HIDDeviceInfo
Caused by: java.lang.ClassNotFoundException: 
com.codeminders.hidapi.HIDDeviceInfo
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
java(1416,0x111dcd000) malloc: *** error for object 0x7f8f9a418010: pointer 
being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

(I am using the trunk version from Jan 26th.)

Original comment by mirkoj...@gmail.com on 27 Feb 2012 at 11:54

GoogleCodeExporter commented 8 years ago
Has anyone been able to get around this problem?

Original comment by shob...@gmail.com on 20 Apr 2012 at 3:20

GoogleCodeExporter commented 8 years ago
I am also having the same issue as mirkoj.  I am experiencing the error via 
Java Web Start. Deploying my app works great, however when I disconnect and 
reconnect the USB connection, I get the same error that mirkoj gets, which 
appears to be a classloader issue.  Can I please get an update on this issue?  
I love this library, however need to have it correctly handle connect and 
disconnect events.

Original comment by shob...@gmail.com on 24 Apr 2012 at 1:06

GoogleCodeExporter commented 8 years ago
I'm also having this same issue. Ive made tests with Virgo Kernel 3.0.3, that 
runs on Equinox.

As a workaround (totally oposed on the modularity that osgi brings) is expose 
the bundle in the System Classpath, adding the API package on the 
"org.osgi.framework.system.packages"

Original comment by edufra...@gmail.com on 14 May 2012 at 5:18

GoogleCodeExporter commented 8 years ago
I'm also get this error. I'm using Netbeans and getting it both in Windows7 and 
OSX. I load the library with System.loadLibrary(). One thing I noticed was that 
in a plain Java Application project this CNFE is not thrown and the connect 
disconnect events in HIDManagerTest work fine. Run the same HIDManagerTest 
example code in a Netbeans Platform Application and I see the CNFE on connect 
AND disconnect. I'm digging for the cause but no luck yet. 
.

Original comment by jemi...@gmail.com on 21 May 2012 at 5:01

GoogleCodeExporter commented 8 years ago
it happens when our classes are loaded by custom classloader, not a system one. 
Try to use this approach to fix it: 
http://blog.tewdew.com/post/6852907694/using-jni-from-a-native-activity

Original comment by b...@codeminders.com on 19 Jul 2012 at 8:35

GoogleCodeExporter commented 8 years ago
Thanks for the comment! I looked at the sample and (as far as I can tell) makes 
my point, that the class loader used in the native library to actually load the 
hidapi classes is not using the custom class loader. So, this has to be fixed 
in the native code and not in the java code AFAIK. With my limited knowledge I 
think the fix should look like this for the javahidapi library part:

...
// this is what was done to load classes (basically asking the system class 
loader
m_env->FindClass(DEVINFO_CLASS)
m_env->FindClass( HID_MANAGER_CLASS );
// instead, I guess the object reference should be asked (if this is actually 
possible,
// to get the current class loader in java and ask that one to load the class
// from the jobject obtained from: registerHIDDeviceCallback(JNIEnv *env, 
jobject obj)
JNIEnv *jni;

state->vm->AttachCurrentThread(&jni, NULL);
jclass classLoader = jni->FindClass("java/lang/ClassLoader");
jmethodID findClass = jni->GetMethodID(classLoader, "loadClass", 
"(Ljava/lang/String;)Ljava/lang/Class;");
// get the manager
jstring strClassName = jni->NewStringUTF("com/codeminders/hidapi/HIDManager");
jclass hidManagerClass = (jclass)jni->CallObjectMethod(obj, findClass, 
strClassName);
// get the device info class
jstring strClassName = 
jni->NewStringUTF("com/codeminders/hidapi/HIDDeviceInfo");
jclass hidDeviceInfoClass = (jclass)jni->CallObjectMethod(obj, findClass, 
strClassName);

Again, I have real experiences in JNI and C++, but that's what I would expect 
how it should work (or at least similar). I was looking at the following method 
in the code: 
http://code.google.com/p/javahidapi/source/browse/jni-impl/HIDManager.cpp#245

Is such a change feasible? 

Thanks in advance,
Mirko

Original comment by mirkoj...@gmail.com on 19 Jul 2012 at 10:56

GoogleCodeExporter commented 8 years ago
I actually wanted to say that I have NO real experiences in JNI and C++ ;-)

Original comment by mirkoj...@gmail.com on 19 Jul 2012 at 10:58

GoogleCodeExporter commented 8 years ago
Hello,

Same problem for me with Windows 7 and latest version (1.1) and no way to solve 
the problem.
Any help is welcome.

Bye,
Hervé

Original comment by herv...@springcard.com on 8 Oct 2014 at 8:44

GoogleCodeExporter commented 8 years ago
Hello,

In my case I solved the problem with a call like this one:
java -cp 
D:\Dev\Java\javahidapi\hidapi.jar;D:\Dev\Java\javahidapi\hidapi-1.1-javadoc.jar;
D:\Dev\Java\javahidapi\hidapi-1.1-sources.jar;D:\dev\Java\hid\dist\hid.jar 
com.mydomain.hid.main

The process needs to be elevated (I'm using Windows 7 / 64 bits), so I used 
Elevate:
http://www.wintellect.com/blogs/jrobbins/elevate-a-process-at-the-command-line-i
n-vista

Bye,
Hervé

Original comment by herv...@springcard.com on 9 Oct 2014 at 8:55