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

Native Library jawt.dll already loaded in another classloader #317

Open
magreenblatt opened this issue Dec 28, 2018 · 8 comments
Open

Native Library jawt.dll already loaded in another classloader #317

magreenblatt opened this issue Dec 28, 2018 · 8 comments
Labels
bug Bug report

Comments

@magreenblatt
Copy link
Collaborator

Original report by Leah (Bitbucket: Leah, GitHub: Leah).


I'm trying to write a plugin for IDEA which integrates chromium as a webview, not sure if this error is on me, but any help would be appreciated

java.lang.UnsatisfiedLinkError: Native Library C:\Users\harmony\.gradle\caches\modules-2\files-2.1\com.jetbrains\jbre\jbrex8u152b1343.15_windows_x64\jre\bin\jawt.dll already loaded in another classloader
	at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1907)
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1845)
	at java.lang.Runtime.loadLibrary0(Runtime.java:870)
	at java.lang.System.loadLibrary(System.java:1122)
	at org.cef.CefApp.<init>(CefApp.java:138)
	at org.cef.CefApp.getInstance(CefApp.java:213)
	at org.cef.CefApp.getInstance(CefApp.java:200)
	at org.panda_lang.pandomium.wrapper.PandomiumCEF.initialize(PandomiumCEF.java:16)
	at org.panda_lang.pandomium.Pandomium.lambda$initialize$0(Pandomium.java:34)
	at org.panda_lang.pandomium.loader.PandomiumLoader.callListeners(PandomiumLoader.java:56)
	at org.panda_lang.pandomium.loader.PandomiumLoaderWorker.load(PandomiumLoaderWorker.java:46)
	at org.panda_lang.pandomium.loader.PandomiumLoaderWorker.run(PandomiumLoaderWorker.java:21)
	at java.lang.Thread.run(Thread.java:745)

It's loaded from here
https://bitbucket.org/chromiumembedded/java-cef/src/d64cd6c266d5a9fc485bdfb6d5b672201dc5dfc7/java/org/cef/CefApp.java?at=master#lines-138

@magreenblatt
Copy link
Collaborator Author

Original comment by Simon Haisz (Bitbucket: sihaisz, GitHub: sihaisz).


This issue happens because another classloader already loaded jawt.dll for some purpose. We ran into this issue because the Java Access Bridge (used for accessibility) loaded the dll first. Likely IDEA itself that is doing it.
The annoying thing is that there is no way to check if a native dll is already loaded apart from trying and catching this exception. This is made more annoying because UnsatisfiedLinkError is used for a variety of errors, some of which should cause your program to crash, so you have to resort to checking the exception message.

This is the work around that we ended up using:

#!java
try {
	System.loadLibrary("jawt"); //$NON-NLS-1$
} catch(UnsatisfiedLinkError e) {
	String message = e.getMessage();
	if(!message.startsWith("Native Library") || !message.endsWith("already loaded in another classloader")) { //$NON-NLS-1$ //$NON-NLS-2$
		throw e;
	}
	System.out.println("Failed loading jawt.dll. It is already loaded by another classloader."); //$NON-NLS-1$
}

Something like this should probably be promoted to master. We didn't create a PR because we have other changes around initialization that only apply to our application.
If you are concerned about trusting your program flow to an exception message that could be changed in any release (and you should be...) please note that our workaround has been in production for 3 years and we haven't had to touch it since.

@magreenblatt
Copy link
Collaborator Author

Original comment by Leah (Bitbucket: Leah, GitHub: Leah).


It's kinda confusing to me that java wouldn't handle that by itself

@magreenblatt
Copy link
Collaborator Author

Original comment by Nol Moonen (Bitbucket: nolmoonen, GitHub: nolmoonen).


Hello, I am having the exact same issue with IDEA. However, I stumbled upon a way to check if the library is loaded, without relying on this exception message flow. It basically comes down to:

try {
    java.lang.reflect.Field libraryNames;
    libraryNames = ClassLoader.class.getDeclaredField("loadedLibraryNames");
    libraryNames.setAccessible(true);
    Vector<String> libraries = (Vector<String>) libraryNames.get(ClassLoader.getSystemClassLoader());
    if (!libraries.contains("jawt")) {
        System.loadLibrary("jawt");
    }
} catch (NoSuchFieldException | IllegalAccessException e) {
    e.printStackTrace();
}

I am quite unsure whether this is something you'd want on the master branch, since it seems like a hack. However, it is still a serious issue to me. Should I make a pull request for this?

@magreenblatt
Copy link
Collaborator Author

Original comment by Max Senft (Bitbucket: Max Senft).


Hmhm, as there’s a pull request (https://bitbucket.org/chromiumembedded/java-cef/pull-requests/39/fix-loading-already-loaded-native-library/diff) now, I wonder if this is actually the correct solution. It looks more like a workaround to me, as the Java documentation states that subsequent calls of loadLibrary() will be ignored (see https://docs.oracle.com/javase/8/docs/api/java/lang/Runtime.html#loadLibrary-java.lang.String-).

I tested this problem by myself, by loading the "jawt" library immediately in Main() of my program and did not get an exception later, when loading the JCEF…

@magreenblatt
Copy link
Collaborator Author

I believe applications should now be able to work around this issue with the SystemBootstrap class added in fbfa9202 (bb).

@magreenblatt
Copy link
Collaborator Author

If SystemBootstrap is insufficient we can re-open.

@magreenblatt
Copy link
Collaborator Author

  • changed state from "new" to "closed"

@magreenblatt
Copy link
Collaborator Author

@magreenblatt magreenblatt reopened this Jan 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Bug report
Projects
None yet
Development

No branches or pull requests

1 participant