使用Manifest文件ClassNotFoundException从可执行JAR启动JAR文件时出现问题

时间:2014-08-02 14:45:11

标签: java mysql jar rmi

我有一个使用RMI和JDBC的项目,我需要使它成为可执行的JAR。现在我的指示是制作一个包含所有源代码的JAR文件,其中包含了我所有的.java文件。我的第二个JAR需要是RMI服务器.class文件,然后第三个JAR将拥有我所有的RMI客户端.class文件。

现在第一个JAR和第三个JAR我没有问题,但问题在于,在我的第二个我需要使用JDBC,所以我需要在其中包含mysql-connector-java-5.1.31-bin.jar文件。

我的文件夹包含以下布局,仅使用默认包,所有内容都在根目录中。

1st JAR - 源代码Jar文件包含...

A2Interface.java
A2InterfaceImpl.java
A2RmiClient.java
A2RmiServer.java
InvalidLocationException.java
DuplicatedAddressException.java

我用这个命令来刺激它

jar cvf source.jar *.java

2nd JAR - 包含与RMI服务器相关的类,我还需要包含mysql JDBC jar文件

我用这个命令来JAR吧

jar cvfm RMIserver.jar server.txt A2RmiServer.class A2Interface.class
A2InterfaceImpl.class *Exception.class mysql-connector-java-5.1.31-bin.jar

我的server.txt清单文件包含以下内容

Main-Class: A2RmiServer
Class-Path: mysql-connector-java-5.1.31-bin.jar
-empty line as per the docs-

3rd JAR - 包含与RMI客户端相关的类

jar cvfm RMIclient.jar client.txt A2RmiClient.class
A2RmiClient$EventHandler.class

任何我的client.txt清单文件都包含

Main-Class: A2RmiClient
-empty line as per the docs-

现在所有的jar都完美无缺,我提取了我的第一个包含所有.java文件的JAR文件,没有任何错误。然后我尝试使用以下命令运行我的RMIserver.jar文件...

首先我启动注册表..

start rmiregistry 5566

然后我运行可执行jar文件..

java -cp mysql-connector-java-5.1.31-bin.jar -jar RMIserver.jar

以下是我得到以下

的例外情况
Trouble: java.rmi.ServerException: RemoteException occurred in server thread; nested    exception is:
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
    java.lang.ClassNotFoundException: A2Interface

我无法确定为什么这样做。如果我不使用任何jar文件,我的代码运行完全没有ZERO异常,但一旦我尝试这个,我总是得到例外。我搜索了很多地方,有些人说你不能包含像这样的mysql JAR文件(或任何JAR文件),甚至根据这里的Java文档http://docs.oracle.com/javase/tutorial/deployment/jar/downman.html

他们还提到它的设计仅用于网络上的JAR,而不是在同一目录中,但是我的教授相信这可以做到。我一直试图弄清楚这几个小时并且已经到了墙上。我不知道如何使用必要的mysql JAR文件使其工作。

OH,请不要提及使用任何其他工具来创建JAR包,因为我无法为我的任务甚至是日食做到这一点。我只能通过严格使用命令行工具来实现这一点。

2 个答案:

答案 0 :(得分:0)

ClassNotFoundException正在 rmiregistry 中发生,并且会以#{1}}的形式返回到您的服务器应用程序。

在正常使用中,RMI服务器使用其代码库URL注释类,以便其他Java进程可以加载未知类。但是,jar文件不是用于此目的的可用URL(我不完全确定,但我认为这是因为从文件中加载它通常是不安全的:从网络)。

当你不使用jar文件时它工作的原因是因为rmiregistry能够在自己的类路径中找到缺少的类(因为你在包含A2Interface.class的同一目录中运行它) )。

您有两种选择:

  1. 从运行在RMI服务器主机上的http服务器提供类文件(或包含它们的jar),并使用java标志ServerException指向类所在的目录/ jar被发现;或
  2. 在每个类路径中插入公共类:server,client和rmiregistry。
  3. 有关详细信息,请参阅http://docs.oracle.com/javase/7/docs/technotes/guides/rmi/codebase.html

答案 1 :(得分:0)

  

这是我得到以下

的例外情况

注册表在其CLASSPATH上没有该类可用。有三种解决方案,难度逐渐增加:

  1. 通过LocateRegistry.createRegistry().在服务器JVM中运行注册表。执行此操作时,必须将该调用的结果存储在静态变量中,以防止对其进行垃圾回收。这也可以在您希望JVM退出时取消导出注册表。

  2. 使用适当的CLASSPATH运行rmiregistry。有几种方法可以做到这一点,包括-J-classpath和设置CLASSPATH环境变量。

  3. 使用RMI代码库功能。

  4.   

    现在我的指示是制作一个包含我所有.java文件的源代码的JAR文件。我的第二个JAR需要是RMI服务器.class文件,然后第三个JAR将拥有我所有的RMI客户端.class文件。

    您的说明不正确。您需要制作四个 JAR文件:

    1. 源代码(为什么?)
    2. 。客户端和服务器共有的.class文件
    3. 。仅在服务器上使用的.class文件
    4. 。仅在客户端上使用的.class文件。
    5. (3)和(4)需要清单,既可以命名Main-Class,也可以命名(2)类路径。

      服务器部署需要(2)和(3)。客户端部署需要(2)和(4)。