Java应用程序在Eclipse上工作正常,但在部署为可运行jar后无法正常工作

问题描述:

就像我说的那样,我的Java应用程序无法正常工作,因为它在Eclipse上开发时工作正常。Java应用程序在Eclipse上工作正常,但在部署为可运行jar后无法正常工作

我完成了在Eclipse上构建和测试我的应用程序。它工作正常,如我所料。我需要将它部署为可运行的jar,以便我的客户端不能在他们的系统上使用它。我通过在Eclipse上导出它来使它成为可运行的jar。 当我运行可运行jar时,应用程序开始正常工作一段时间并停止文件读取。我在Eclipse上使用相同的代码没有任何问题。

似乎不起作用的源代码片段如下。

  sfis = new SmbFileInputStream(sFile); 
      in = new BufferedInputStream(sfis); 

      byte buf[] = new byte[(int)sFile.length()]; 
      int pos = 0; 
      int size = 10; 
      int temp; 

      while((size=in.read(buf, pos, size)) > 0){ 
       pos += size; 
       temp = buf.length - pos; 
       if(temp < 10){ 
        size = temp; 
       } 
      } 

在Eclipse上它不会引起任何问题。它完美地读取来自SMB连接的数据并完成其工作。但是从jar应用程序来看,似乎在某些时候停止从inputstream内部读取while循环。 这是一个非常奇怪的案例,我从来没有经历过。我找不到任何解决方案。

这是因为我的代码或Eclipse文件可能会错误地生成jar文件吗?

----------其他信息-------------------

与Edmondo1984一个很大的帮助,我找出jar程序停止。 当它从SmbFile进入inputstream时,会创建一个新的线程jcifs.util.transport.Transport,并简单地阻塞该线程,并且该应用程序将创建另一个jcifs.util.transport.Transport等等。在创建了8个或9个jcifs.util.transport.Transport线程之后,它被卡住,无所事事。

相同的代码,相同的jcifs库。但是,在Eclipse上运行并在本地机器上作为可运行的jar工作方式不同。 我不知道为什么会发生这种情况。

+0

的Eclipse可能无法把正确的罐子在您的“包装罐子”,但是这通常会导致类加载的错误。你在同一个文件上测试吗? – Edmondo1984 2012-07-19 07:49:13

+0

你必须给自己一些可见的指示器。也就是说,在一次尝试中发现了一些有关已发生事情的意义信息。上面的错误消息对调试正在发生的事情很有用。 – Davos555 2012-07-19 08:23:41

+0

@ Edmondo1984像你说的,如果Eclipse中无法添加应用程序所需的一些图书馆,它不会启动。但它开始运行。噢,我正在测试同一个文件。 – user1537096 2012-07-19 08:34:02

“流上没有其他东西”的返回值是-1(请参阅Javadoc)。

想象一下,如果您尝试in.read(buf, pos, size)但底层仍不可用,会发生什么情况。然后该呼叫立即返回,返回值为0(零)。这样,循环条件评估为false并退出循环。所以我认为你应该与!= -1比较。

另一个可能的问题:您也可以考虑如果size = 0(例如由于上述情况)和temp >= 10会发生什么情况。由于您直接将size的值反馈为in.read(buf, pos, size)作为要读取的最大字节数,因此您可能会以无限循环结束,假设您已将该比较更正为!= -1

+0

感谢您的回复,但您的解决方案也无法正常工作。正如我所解释的,它在Eclipse上工作正常。如果你所说的是一个真正的问题,那么这个应用程序也不能在Eclipse上工作。 – user1537096 2012-07-19 10:10:52

+0

只要'read()'总是返回至少一个字节的读(这绝对不能保证),你不会遇到任何麻烦。我发现代码和文档的假设不匹配。从这个角度来看,我猜测如果假设没有得到满足(如上所述)会发生什么。正如Tiago在他的回答中指出的那样,Eclipse和JAR之间可能有不同的运行时行为。 – cyroxx 2012-07-19 20:21:44

当插入流时,这些行为是频繁的。小算法错误可能导致不同环境中的不同症状。

您可以将“调试”信息打印到控制台,以更好地了解代码停滞的位置和原因。我很确定它的读取方法。

有几件事情你的代码错误,其中最臭名昭著的是块:

temp = buf.length - pos; 
if(temp < 10){ 
    size = temp; 
} 

为什么?当有10个或更少的字节留给你会尝试在一个read()读取它们,否则你可能会试图读取太多(整个文件再次大小)。在Eclipse中运行时,该文件可能在第一次读取()时读取,显然不是Eclipse。 尝试更改您的代码是这样的:

FileInputStream sfis = new FileInputStream(sFile); 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
byte buf[] = new byte[4096]; 
int read = sfis.read(buf); 
while(read>0){ 
    baos.write(buf, 0, read); 
    read = sfis.read(buf); 
} 
sfis.close(); 

也可以考虑使用Apache's Java IO utilities代码,而不是总是写这种类型的代码。 Java中的IO需要大量的样板,一个好的程序员有更好的事情要做。

在一个侧面说明:读文件到内存通常是一个坏主意。除非你以某种方式整体转换数据,否则流媒体总是更好。我不知道您的程序是什么,但请记住这一点:如果您尝试读取10GB文件,会发生什么情况?或几个?

快乐编码,

+0

感谢您的回复。我之所以对你提到的部分做这件事,是为了让文件阅读更快一点。我知道这并没有太大的作用,但是应用程序读取的文件通常少于30 MB,所以我需要这种算法。至于你的代码,我也试过了,但同样的事情发生了,而且这次它比以前更早发生。 – user1537096 2012-07-19 11:04:17

Java是大写字母敏感evry的方式。例如,如果您有一个名为image.PNG文件,并在你的代码为“/image.png”(而不是“/image.PNG”),将工作在Eclipse罚款,但出口运行的JAR文件的Java虚拟机将后置位置无法找到该文件。