0

我有一个用 Java 编写的大型系统,它基本上由用户界面、应用程序的“核心引擎”和许多其他模块组成。我正在尝试创建一个仅包含“核心引擎”而不包含其他部分的小程序,因此我需要共享相同的代码库以跟上更新。我已经这样做并且效果很好,问题是在我不需要的其他部分中使用了很多外部jar,而小程序目前需要它们。

我没有调用需要外部 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 跟踪都是相同的,但缺少其他文件。另外,在这个系统上,我有多个版本(例如学术版和商业版),并且很多需要的 jar 不在学术版中,但我可以使用相同的代码编译其他版本,而无需需要这些罐子时遇到问题。

我知道提供帮助是一种艰难的情况,但我认为也许有人处于类似情况并且可以给我一个提示。

另外,有没有可能我有一些方法,比如:

public void myMethod() {
 ClassInOneOfTheJars c = new ClassInOneOfTheJars();
}

但这种方法永远不可能让虚拟机尝试获取包含 ClassInOneOfTheJars 的 jar?(据我所知,答案似乎是“不”)。

4

3 回答 3

1

根据评论,发生的事情是,只有在尝试加载MyClass2时,JVM才会less.jar在搜索类路径时尝试访问。我的猜测是,仅在第一次需要类时才加载类,因此.jar仅当在以前的类中找不到类时才首先访问 s / 其他类路径条目。

解释您看到的行为的一种方法是您的类路径.jar按以下顺序包含这些 s:

  1. a.jar(当地的)
  2. less.jar(偏僻的)
  3. b.jar(当地的)

MyClass在哪里a.jar; 并且MyClass2b.jar. 类加载器尝试加载MyClass、打开a.jar、在那里找到并加载它,然后开始运行构造函数。构造函数需要MyClass2,所以类加载器打开a.jar,在那里找不到类,然后移动到下一个类路径条目。这是less.jar,这是不可访问的,你得到了崩溃。当您.jar从类路径中删除不可访问的内容时,类加载器可以继续前进b.jar并找到MyClass2那里。

于 2012-08-01T11:04:57.140 回答
0

原因是在 中MyClass2使用了一些东西less.jar,因此导致了错误。

于 2012-08-01T01:51:26.110 回答
0

注意线

at my.package.MyClass.<init>(MyClass.java:187)

这意味着MyClass正在初始化一个类型的对象。我敢打赌,第 187 行是内联构造函数调用,构造函数主体内的一行,或者是默认字段值初始化。

初始化最终试图在 中加载一些东西jess.jar,这就是导致错误的原因。

于 2012-08-01T02:13:45.600 回答