我有一个Java系统,它基本上由用户界面,应用程序的“核心引擎”和许多其他模块组成。 我正在尝试创建一个仅包含“核心引擎”的applet,而不包含其他部分,因此我需要共享相同的代码库以跟上更新。 我已经完成了这个并且效果很好,问题是在我不需要的其他部分中使用了很多外部jar,而applet目前都需要它们。
我不调用需要外部jar的代码的一部分,当我调用类的构造函数时,堆栈跟踪给我一个错误,所以我猜的是它需要一个罐子尽快这个类(我正在使用构造函数)被加载。但我在互联网上看到Java只在需要时才加载类,所以我不确定这里发生了什么。有人可以给我一些建议,我怎么能让它不需要这些罐子?
PS:我确信最好的方法是重构它,将功能分成清晰的层,这样我就可以更轻松地解决这个问题。问题是,这是一个非常古老而庞大的代码库,并且正在进行这种大规模重构(尽管我希望)现在还不可行。编辑 - 添加其中一个堆栈跟踪和更多信息:
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第187行只是: MyClass2 obj = new MyClass2();
所有其他FileNotFoundException跟踪相同,但缺少其他文件。 此外,在这个系统上,我有一个以上的版本(学术版和商业版,例如),并且许多需要的罐子不在学术版本中,但我可以使用相同的代码编译其他版本有问题需要这些罐子。
我知道提供帮助是一种艰难的情况,但我可能会有人遇到类似的情况而且可以给我一些暗示。
另外,有没有机会我有一些方法,如:
public void myMethod() {
ClassInOneOfTheJars c = new ClassInOneOfTheJars();
}
但是这种方法永远不可能让VM尝试获取包含ClassInOneOfTheJars的jar吗? (据我所知,答案似乎是'不')。
答案 0 :(得分:1)
根据评论,发生的事情是,只有在尝试加载MyClass2
时,JVM才会在搜索类路径时尝试访问less.jar
。我的猜测是,只有在第一次需要时才会加载类,因此.jar
s /其他类路径条目只有在以前的类中找不到类时才会首次访问。
解释您看到的行为的一种方法是,您的类路径按以下顺序包含这些.jar
:
a.jar
(本地)less.jar
(远程)b.jar
(本地) MyClass
位于a.jar
的位置; MyClass2
位于b.jar
。类加载器尝试加载MyClass
,打开a.jar
,在那里找到它并加载它,然后开始运行构造函数。构造函数需要MyClass2
,因此类加载器打开a.jar
,在那里找不到类,然后转到下一个类路径条目。这是less.jar
,这是无法访问的,你得到了崩溃。当您从类路径中删除无法访问的.jar
时,类加载器可以转到b.jar
并在那里找到MyClass2
。
答案 1 :(得分:0)
原因是MyClass2
使用less.jar
中的内容,从而导致错误。
答案 2 :(得分:0)
注意这一行
at my.package.MyClass.<init>(MyClass.java:187)
这意味着正在初始化类型为MyClass
的对象。我敢打赌第187行是内联构造函数调用,构造函数体内的一行,或者是默认的字段值初始化。
初始化最终试图加载jess.jar
中的内容,这就是导致错误的原因。