Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null ContextClassLoader in new threads #582

Closed
audetto opened this issue Feb 11, 2021 · 2 comments
Closed

Null ContextClassLoader in new threads #582

audetto opened this issue Feb 11, 2021 · 2 comments
Labels

Comments

@audetto
Copy link

audetto commented Feb 11, 2021

I am facing an issue whereby the ClassLoader seems unable to load classes in separate threads.

This is the error I get
SEVERE: MASM0010: Unable to unmarshall metro config file from location [ jar:file:/E:/dev/code/java-lib/someapi.java8-12.0.7773.jar!/META-INF/jaxws-tubes-default.xml ]

It is not linked to a particular java version, happens in 8, 11 and 14. It started happening when I upgraded a 3rd party lib, which I have little control over.
I am using jnius 1.3 in python 3.6.6 in Windows 7 64 bit.

After a lot of debugging I noticed that

jnius.autoclass('java.lang.Thread').currentThread().getContextClassLoader()

returns None in all new threads. And this explains why it cannot find the file which is indeed present in the jar. Maybe the 3rd party lib has changed the exact dynamic of class loading and now does it in each new thread.

One way to fix this is to mirror the Android wrapper, https://github.com/kivy/pyjnius/blob/master/jnius/__init__.py#L76:

import threading
import jnius
 
classloader = jnius.autoclass('java.lang.ClassLoader').getSystemClassLoader()
orig_thread_run = threading.Thread.run
def jnius_thread_hook(*args, **kwargs):
    jnius.autoclass('java.lang.Thread').currentThread().setContextClassLoader(classloader)
    return orig_thread_run(*args, **kwargs)

threading.Thread.run = jnius_thread_hook

but I really think I am missing something here. Does jnius require any particular setup to work in multiple threads?

@audetto
Copy link
Author

audetto commented Feb 12, 2021

These are probably relevant:
https://stackoverflow.com/questions/18354535/why-do-subsequent-jni-threads-return-null-on-currentthread-getclassloader/29194820

and

https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html

around Attaching to the VM, it says

Should another thread need to access the Java VM, it must first call AttachCurrentThread() to attach itself to the VM and obtain a JNI interface pointer. Once attached to the VM, a native thread works just like an ordinary Java thread running inside a native method. The native thread remains attached to the VM until it calls DetachCurrentThread() to detach itself.

and below

When a thread is attached to the VM, the context class loader is the bootstrap loader.

I can see that jnus uses AttachCurrentThread:

# XXX it threads are created from C (not java), we'll leak here.

and the comment is a bit worrying.

What is the exact status of jnius with python-created threads?

@github-actions
Copy link

👋 We use the issue tracker exclusively for bug reports and feature requests. However, this issue appears to be a support request. Please use our support channels to get help with the project.
Let us know if this comment was made in error, and we'll be happy to reopen the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants