I have a large system in Java, which basicaly consists of an user interface, the “core engine” of the application and a lot of other modules.
I am trying to create an applet that will consist only of the “core engine”, without the other parts, so I need to share the same codebase to keep up with the updates.
I’ve done this and it works well, the problem is that there are a lot of external jars used in the other parts that I don’t need, and the applet currently requires them all.
I don’t call the part of the code that needs the external jar and the stack trace gives me an error when I am calling a constructor of a class, so what I am guessing is that it requires the jars as soon as this class (that I’m using the constructor) is loaded. But I’ve read on the internet that Java only loads classes when required, so I’m not sure what is going on here. Could anybody give me some advice about how can I make it not need these jars?
PS: I’m sure the best approach would be to refactor it, separating the functionality into clear layers, so I could tackle this more easily. The problem is that this is a very old and big codebase and doing this kind of mass-refactoring (although I would like to) is not viable right now.
Edit – adding one of the stack traces and more information:
java.io.FileNotFoundException: http://localhost:3000/applet/jess.jar
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at com.sun.deploy.net.DownloadEngine.getJarFileWithoutCache(Unknown Source)
at com.sun.deploy.net.DownloadEngine.downloadJarFileWithoutCache(Unknown Source)
at sun.plugin.PluginURLJarFileCallBack$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin.PluginURLJarFileCallBack.retrieve(Unknown Source)
at sun.net.www.protocol.jar.URLJarFile.retrieve(Unknown Source)
at sun.net.www.protocol.jar.URLJarFile.getJarFile(Unknown Source)
at sun.net.www.protocol.jar.JarFileFactory.get(Unknown Source)
at sun.net.www.protocol.jar.JarURLConnection.connect(Unknown Source)
at sun.plugin.net.protocol.jar.CachedJarURLConnection.connect(Unknown Source)
at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFileInternal(Unknown Source)
at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFile(Unknown Source)
at com.sun.deploy.security.DeployURLClassPath$JarLoader.getJarFile(Unknown Source)
at com.sun.deploy.security.DeployURLClassPath$JarLoader.access$1000(Unknown Source)
at com.sun.deploy.security.DeployURLClassPath$JarLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.deploy.security.DeployURLClassPath$JarLoader.ensureOpen(Unknown Source)
at com.sun.deploy.security.DeployURLClassPath$JarLoader.<init>(Unknown Source)
at com.sun.deploy.security.DeployURLClassPath$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
at com.sun.deploy.security.DeployURLClassPath.getResource(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin2.applet.Plugin2ClassLoader.findClassHelper(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at my.package.MyClass.<init>(MyClass.java:187)
at my.package.MyApplet.start(MyApplet.java:38)
at com.sun.deploy.uitoolkit.impl.awt.AWTAppletAdapter.start(Unknown Source)
at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
MyClass line 187 is just:
MyClass2 obj = new MyClass2();
All other FileNotFoundException traces are identical, but missing other files.
Also, on this system, I have more than one release (academic and commercial version, for exemple) and a lot of the jars that are being required are not in the academic version, but I can compile the other versions using the same code without having problems with it needing these jars.
I know is kind of a tough situation to give help, but I though that maybe someone has been in a similar situation and could give me a hint.
Also, is there any chance that the fact that I have some method like:
public void myMethod() {
ClassInOneOfTheJars c = new ClassInOneOfTheJars();
}
but never could this method could make the VM try to fetch the jar that contains ClassInOneOfTheJars? (As far as I’ve read, it seems like the answer would be ‘no’).
Based on the comments, what happened is that only when trying to load
MyClass2did the JVM try and accessless.jarwhen searching the classpath. My guess is that just how classes are only loaded when they’re needed the first time, so are.jars / other classpath entries only first accessed when a class is not found in the previous ones.One way to explain the behaviour you see is that your classpath contains these
.jars in the following order:a.jar(local)less.jar(remote)b.jar(local)Where
MyClassis ina.jar; andMyClass2is inb.jar. The classloader tries to loadMyClass, opensa.jar, finds it there and loads it, and starts running the constructor. The constructor needsMyClass2, so the classloader opensa.jar, doesn’t find the class there, and moves on to the next classpath entry. This isless.jar, which is inaccessible, and you get the crash. When you removed the inaccessible.jarfrom the classpath, the classloader can move on tob.jarand findsMyClass2there.