[英]Strange behavior with different java application export option
我有java服務器應用程序,它使用很多庫(netty,guava等)。 我總是將此應用程序導出為單個.jar。 當我在Eclipse中運行應用程序時,我沒有任何問題。 但是,如果我在控制台(Windows或Ubuntu,無關緊要)啟動應用程序,我有一個奇怪的問題:通過套接字的所有連接進程持續太長時間。 例如,通過HttpAsync或其他人(rabbitmq連接等)的簡單http連接持續1-2分鍾。 但連接完成后,數據發送/接收速度很快。 我無法弄清楚是什么問題。 如前所述,我使用Eclipse進行開發。
如您所知,您可以導出項目3方式(在Eclipse中):
所以,當我使用2選項時,我遇到了問題。 當我切換到3d選項(main .jar附近的文件夾中的所有.jars)時,問題就解決了。
通常情況下,2和3選項之間沒有太大區別(2個所有.jars只在一個jar內)。 我認為這是從jar開始在執行時加載新類所需的額外時間的原因。 但問題不僅發生在開始,而且發生在所有新連接上。
有人可以解釋這種行為嗎?
UPD: Eclipse Luna。 無論我使用什么操作系統(Windows,或Ubuntu),甚至無關緊要jvm(嘗試使用不同的Oracle jdk,甚至嘗試打開jdk)。
這一切都討論了在從JAR v / s解壓縮到JAR時的性能差異以及從從控制台運行的Eclipse v / s運行時的性能差異。
它能做什么:
在此選項中,Eclipse將從引用的JAR和包中提取所有類到生成的JAR中。
如果打開JAR,那么您會發現沒有打包引用的JAR,但所有引用的JAR類都按照包結構排列,然后在根級別打包在JAR中。 與“將所需的包裝到jar文件中”相比,這帶來了性能上的關鍵差異,其中還存在運行時解析和在內存中加載JAR等成本。
當通過Eclipse導出為JAR時,如果關注性能,則最好選擇。 這也是可擴展的選項,因為您可以發送此JAR
MANIFEST.MF這個文件中要注意的主要是你的主要課程。 當您運行JAR時,您將直接運行所需的類。
Main-Class: com.my.jar.TestSSL
它能做什么:
在這個選項中,Eclipse將:
org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
使用Eclipse的JAR加載機制,你也可以在你生成的JAR中看到org.eclipse.jdt.internal.jarinjarloader
包,這個包就在生成的JAR的根目錄下。 當然這當你選擇這個選項時會產生額外的成本,因為當你運行JAR時,你不是主類被執行,而是執行JarRsrcLoader
,這將加載你的主類和其他庫,以及所有引用的庫包裝好了。 請參閱下面的MANIFEST.MF部分
MANIFEST.MF這個文件中要注意的主要是你的主要課程。 當您運行JAR時, JarRsrcLoader
將運行並將繼續工作。
Rsrc-Main-Class: com.cgi.tmi.TestSSL
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
現在對於最后一個Eclipse導出選項 - “將所需的庫復制到JAR旁邊的子文件夾” ,我認為這不是一個非常可擴展的解決方案,因為這會強制您的文件系統依賴,所以我想不要這樣做。
當你從Eclipse運行應用程序時,它很安靜,類似於第一個導出選項,其中Eclipse不需要在運行時解析和加載JAR。
然而,這是一個非常簡單的觀點,關鍵是考慮Eclipse JAR導出選項1 v / s選項2。
由於我們不知道JAR的確切結構,因此這是一個更一般的解釋(假設您使用java -jar your_app.jar
運行應用程序)。
case 將所需的庫復制到JAR旁邊的子文件夾中。
your_app.jar
以查找所需的類 case將所需的庫打包到JAR中
your_app.jar
以查找所需的類 your_app.jar
解壓縮才能讀取內容 如果你有更多的hugh嵌入式庫JAR,這可能會導致類加載速度變慢(但只是第一次類加載器加載一個類)。
如果你比較的是outpout,你可以看到類加載的差異
java -verbose:class -jar your_app_external_library_jars.jar
同
java -verbose:class -jar your_app_embedded_library_jars.jar
通過為每個JAR文件(例如your_app.jar
和嵌入式庫JAR)生成INDEX.LIST
文件,可以提高性能。
在第二種方法中,您在main.jar中擁有所有依賴項jar。 因此除非需要,否則它不會加載任何依賴jar。 然而,在第3個選項的情況下,你的main.jar和其他依賴jar是獨立的(不像第二種方式),因此可以加載連接並且可用。
嘗試通過操作依賴jar來添加日志語句或syso以查看此工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.