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

时间:2012-07-19 07:43:19

标签: java jar inputstream

就像tile说的那样,我的Java应用程序无法工作,因为它在Eclipse上开发时工作正常。

我完成了在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应用程序中,似乎在某些时候停止从输入流内部读取循环。 这是一个我从未经历过的非常奇怪的案例。我找不到任何解决办法。

这是因为我的代码还是可能由Eclipse错误制作的jar文件?

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

在Edmondo1984的大力帮助下,我找到了jar程序停止的位置。 当它从SmbFile转到inputstream时,会创建一个新线程jcifs.util.transport.Transport,并且只是阻塞该线程,并且应用程序会创建另一个jcifs.util.transport.Transport,依此类推。在创建8或9个jcifs.util.transport.Transport线程后,它被卡住并且什么都不做。

相同的代码,相同的jcifs库。但在Eclipse和本地机器上运行作为可运行的jar之间的工作方式不同。 我不知道为什么会这样。

3 个答案:

答案 0 :(得分:2)

“流上没有其他内容”的返回值为-1(请参阅Javadoc)。

想象一下,如果你尝试in.read(buf, pos, size)会发生什么,但底层仍然无法使用。然后调用立即返回,返回值为0(零)。这样,循环条件的计算结果为false,并退出循环。所以我认为你应该与!= -1进行比较。

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

答案 1 :(得分:1)

当介入流时,这种行为很常见。小算法不正确可能会在不同的环境中引起不同的症状。

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

您的代码有几个问题,最臭名昭着的是阻止:

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文件会发生什么?还是几个?

快乐编码,

答案 2 :(得分:0)

Java是大写字母敏感的。例如,如果您有名为image.PNG的文件,并且在您的代码中将位置设置为“/image.png”(而不是“/image.PNG”)它将在eclipse中正常工作,但在导出runnable jar文件之后java VM将无法找到该文件。