Hi everyone,
We've been testing our application out on mac, unfortunately it tends to fail as an old version of Java3D is present in the java extensions directory, and these libraries are loaded before the ones packaged in our fat jar. Does anyone know of any solution to this (aside from running java with -Djava.ext.dirs="")? We've attempted to user our own class loader, and the classes load correctly but the libraries in the extensions directory interfere once again, and we end up with the following error: Exception in thread "AWT-EventQueue-0" java.lang.VerifyError: (class: javax/media/j3d/Canvas3D, method: <init> signature: (Ljava/awt/GraphicsConfiguration;Z)V) Bad type in putfield/putstatic at org.tim32.seg.gui.RunwayDisplay3D.<init>(RunwayDisplay3D.java:47) at org.tim32.seg.gui.MainFrame.init(MainFrame.java:79) at org.tim32.seg.Main$1.run(Main.java:61) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733) at java.awt.EventQueue.access$200(EventQueue.java:103) at java.awt.EventQueue$3.run(EventQueue.java:694) at java.awt.EventQueue$3.run(EventQueue.java:692) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:703) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138) at java.awt.EventDispatchThread.run(EventDispatchThread.java:91) Cheers, Arthur |
Administrator
|
This post was updated on .
Hi
The user "Runiter" builds Java3D after modifying the package names in order to avoid conflicts with the obsolete versions of Java3D. I wrote in my tutorial that the mechanism of extensions shouldn't be used for that purpose but there are still a lot of people who go on doing so :( This is the only "solution" I see, I know that it isn't really satisfying. If you find something better, let us know. Edit.: I haven't found any solution to build a classloader inheriting of the system classloader, respecting the class path but skipping the installed extensions classloader.
Julien Gouesse | Personal blog | Website
|
Hi Julien,
I guess we'll have to settle for renaming the packages to avoid the conflicts - it seems messy, but at least it'll work. I've written a simple class loader that inverses the Java class loader chain - it checks first if the class is available in our fat JAR, and only calls it's parent class loader if it can't find it. This works fine for loading our classes in, unfortunately the jvm seems to be using a different class loader for actually verifying the signature of the files, and not our own. Cheers, Arthur |
Administrator
|
I see what you mean... If we could just force the JVM to ignore extensions, it would work flawlessly.
Maybe you can change the context class loader used while signing, it's only a supposition.
Julien Gouesse | Personal blog | Website
|
Administrator
|
In reply to this post by rthur
Why is it problematic for you to use "-Djava.ext.dirs="""? Actually, this is the best solution to me as the impact is only on your own application, you don't modify the system, your end users don't have to uninstall their extensions, you just specify that your application is going to ignore their extensions. I find your trick acceptable but I would like to know why you don't consider that as a "good" solution.
I will probably use it for my JOGL application because some developers have the bad idea of installing JOGL 1 directly in the JVM :s Edit.: I will update my tutorial soon.
Julien Gouesse | Personal blog | Website
|
Programmatically being able to tell the JVM to ignore the extension directories would be very ideal - I'm still trying to figure out a way to do this via a custom class loader (I'll post it here if I get it to work).
We're using this for a university assignment, which unfortunately means we're subject to some rather idealistic requirements - our application must be bundled as a single jar, and the user needs to be able to just "double-click it". Having a separate launcher that would run our Jar with -Djava.ext.dirs="" would otherwise be a pretty easy solution to this mess. Cheers, Arthur |
Administrator
|
You can set it extremely early in your source code by calling System.setProperty(). Anyway, "runnable" JAR is not a reliable way of deploying applications as even the default archiver may open it as a ZIP instead of using Java, this is one of the known problem. Java Web Start has become harder to use...
Julien Gouesse | Personal blog | Website
|
I've tried setting it as early as I could (in the static initializer of the class that contains main), but to no avail.
I'll agree that a single fat Jar isn't the best way to distribute an application, but unfortunately my hands are tied. I ended up recompiling the java3D packages with different package names so as to avoid conflicts - I can share them here if anyone is interested. Cheers, Arthur |
This post was updated on .
Easiest way I could find was to use jarjar tool to rename all j3d packages in all the jar files. It's very easy to use and will save you time from recompiling Java3D yourself.
The tool is here: https://code.google.com/p/jarjar/wiki/CommandLineDocs I made the following rule.txt file: rule javax.media.j3d.** javax1.media.j3d.@1 rule com.sun.j3d.** com1.sun.j3d.@1 I made a bat file with the following command lines: java -jar jarjar-1.4.jar process rules.txt java3d\j3dcore.jar java3d-jarjar\j3dcore.jar java -jar jarjar-1.4.jar process rules.txt java3d\j3dutils.jar java3d-jarjar\j3dutils.jar java -jar jarjar-1.4.jar process rules.txt java3d\vecmath.jar java3d-jarjar\vecmath.jar
Saeid Nourian, Ph.D. Eng. | Graphing Calculator 3D
|
Administrator
|
In reply to this post by rthur
Does it work when you use at as a VM option?
Julien Gouesse | Personal blog | Website
|
Administrator
|
If someone could confirm in which cases my suggestion works with a recent Mac, I would be very happy and I could update my tutorial about Java3D. @Runiter Please could you try to do it? My Mac is too old, it would be better if someone having at least Mac OS X 10.7.2 could test.
Julien Gouesse | Personal blog | Website
|
Using the VM option works, but setting is programmatically does not as far as I can tell. I've tested this on several macs running mavericks.
Cheers, Arthur |
Administrator
|
Thank you very much rthur. Some people claimed that the classloaders are created so early that this option has no chance to work if not set as a VM option, subsequent changes are simply ignored. Therefore, you can use Runtime.exec in a new main class to "run" the VM with the proper option. This trick is useful to set other VM options, for example Xmx and Xms.
Julien Gouesse | Personal blog | Website
|
No problem, thanks for all your help with this.
I still haven't gotten the classLoader to work properly - it still fails when checking the signature of some methods, I don't think there's much I can do about that.. I looked into using System.exec() (well process builder), but it felt pretty sketchy to be launching our own application again, and relying on the environment variable JAVA_HOME. |
Administrator
|
I suggested to do that:
http://stackoverflow.com/a/2848352 No you don't run your application twice, you just use a small class to run it once.
Julien Gouesse | Personal blog | Website
|
Free forum by Nabble | Edit this page |