2012-07-19 145 views
4

就像我說的那樣,我的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

回答

2

「流上沒有其他東西」的返回值是-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

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文件,會發生什麼情況?或幾個?

快樂編碼,

+0

感謝您的回覆。我之所以對你提到的部分做這件事,是爲了讓文件閱讀更快一點。我知道這並沒有太大的作用,但是應用程序讀取的文件通常少於30 MB,所以我需要這種算法。至於你的代碼,我也試過了,但同樣的事情發生了,而且這次它比以前更早發生。 – user1537096 2012-07-19 11:04:17

0

Java是大寫字母敏感evry的方式。例如,如果您有一個名爲image.PNG文件,並在你的代碼爲「/image.png」(而不是「/image.PNG」),將工作在Eclipse罰款,但出口運行的JAR文件的Java虛擬機將後置位置無法找到該文件。

相關問題