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

Meta Object loading system doesn't use custom classloaders - can't find classes from downloaded jars #92

Closed
mchistovib opened this issue Oct 18, 2022 · 4 comments

Comments

@mchistovib
Copy link

mchistovib commented Oct 18, 2022

Describe the bug
If you use a custom classloader, for example when some of your classes are in downloaded jar, jambi uses the most basic default classloader and it fails to download any classes from that jar.

To Reproduce
This is just one example of the bug, feature.partitions.PortfolioPartitionScope class is in downloaded jar.
2022-10-18 15:54:08.309 [LS] ERROR [JTS-Main] - Got nested exception in qt event
java.lang.ClassNotFoundException: feature.partitions.PortfolioPartitionScope
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
at io.qt.core.QMetaType.qRegisterMetaType(Native Method)
at io.qt.internal.QtJambiInternal.registerMetaType(QtJambiInternal.java:2794)
at io.qt.internal.MetaObjectTools.buildMetaData(MetaObjectTools.java:1297)
at io.qt.core.QAbstractTableModel.initialize_native(Native Method)
at io.qt.core.QAbstractTableModel.(QAbstractTableModel.java:57)
at io.qt.core.QAbstractTableModel.(QAbstractTableModel.java:49)
at ibkr.portfolio.PortfolioPositionsModelView.(PortfolioPositionsModelView.java:485)
We set all threads with classloader that knows about the sdownloaded jar, but QMetaType.qRegisterMetaType is not using these overridden classloaders.
We also tried changing system classloader using -Djava.system.class.loader=YourClassloader - QMetaType.qRegisterMetaType does not use that classloader too..

Expected behavior
.QMetaType.qRegisterMetaType must correctly use Thread classloader, or in the worst case at least use classloader passed from -Djava.system.class.loader

System (please complete the following information):

  • OS: Windows
  • Java version 11
  • QtJambi version All Versions, but more noticeable now in 6.2.8/6.3.5/6.4.0
  • Qt version

Additional context

We belive this happens because in most places like qtjambimetaobject.cpp jclass QtJambiMetaObject::javaClass() a simple env->FindClass(getJavaName(*typeId)) is used, that does not look for any thread attached classloaders or overidden system classloader and intead simply uses jdk.internal.loader.BuiltinClassLoader.

Correct implementation should look like in qtjambi_registry.cpp jclass findClass(JNIEnv *env, const char *qualifiedName, jobject classLoader = nullptr) - it actually checks for thread classloader and uses it if default one didn't find the class.
Please use similar approach for classes that you load in QMetaType.qRegisterMetaType

If possible, please replace all env->FindClass() calls with correct implemntation that checks for custom classloader

@mchistovib mchistovib changed the title Meta Object loading system doesn't use custom classloaders - can't find classes from donloaded jars Meta Object loading system doesn't use custom classloaders - can't find classes from downloaded jars Oct 19, 2022
@omix
Copy link
Contributor

omix commented Oct 19, 2022

It's defiitely not env->FindClass(getJavaName(*typeId)) because typeId is only available for Qt types.
In my opinion, it's caused by function qtjambi_class_for_metatype in qtjambi_functions.cpp. Here, resolveClass is called without classloader. Thus, there is no search beyond env->FindClass(name). As I inspected the code, I saw some legacy lines about class loader management I never touched.

Try to put your downloaded jar into following property:

System.setProperty("io.qt.qtjambi.internal.urlbase", "path to jar file");

QtJambi should now be able to load classes from the URL.

@mchistovib
Copy link
Author

mchistovib commented Oct 19, 2022

del

@mchistovib
Copy link
Author

mchistovib commented Oct 19, 2022

Try to put your downloaded jar into following property:

Thanks, that workaround worked. Could you please also fix the qtjambi_class_for_metatype issue in the next release? (not p1 urgent now)

@omix
Copy link
Contributor

omix commented Oct 19, 2022

The next release will save class references instead of class names for QMetaTypes. Thus, no need to find these classes in whatever classloader. Also I will remove the io.qt.qtjambi.internal.urlbase option and let QtJambi try to use the thread's context classloader.

omix added a commit that referenced this issue Nov 10, 2022
Bugfix Issue #98
Bugfix Issue #92
Bugfix Issue #93
Bugfix Issue #94
@omix omix closed this as completed Nov 10, 2022
omix added a commit that referenced this issue Jul 25, 2023
Bugfix Issue #98
Bugfix Issue #92
Bugfix Issue #93
Bugfix Issue #94
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants