IDEA命令行縮短器助你解決此問題:Command line is too long. Shorten command line...


生命太短暫,不要去做一些根本沒有人想要的東西。本文已被 https://www.yourbatman.cn 收錄,里面一並有Spring技術棧、MyBatis、JVM、中間件等小而美的專欄供以免費學習。關注公眾號【BAT的烏托邦】逐個擊破,深入掌握,拒絕淺嘗輒止。

前言

各位小伙伴大家好,我是A哥。最近遇到兩個問題,都是關於IDEA的(言外之意和代碼無關),很是讓我“生氣”呀(關鍵是浪費時間)。在痛定思痛后,我決定寫此專欄,來專門分享/記錄使用IntelliJ IDEA過程中遇到的那些奇葩問題和解決方案,以幫助你縮短日常排錯時間,這么一思考好像還功德無量呢😄。

IntelliJ IDEA作為Java開發者中最為流行的開發工具(eclipse粉勿噴),熟練掌握它(包括排雷)對提升編碼效率能有顯著提升。但工具畢竟是工具,這么長時間使用IDEA以來,每個人或多或少的都遇到過關於IDEA七七八八、奇奇怪怪的問題,這些與代碼舞棍,但它很容易偷走你的時間,半天又更或者是一天之久。

說明:千萬不要忽視對IDEA的研究,因為把它玩熟練了它就相當於你的物理外掛

本專欄內容並非 IDEA教程,而是着眼於分享IDEA使用過程中,那些我遇到(或者大家遇到)的但又不是能夠很快速解決,總之就是比較棘手的問題的匯總,有一種錯題本的意思有木有。總之就是希望它能夠幫助到大家迅速定位or解決問題,避免不必要的時間浪費,畢竟咱們的主業還是敲代碼嘛~


版本約定

本文內容若沒做特殊說明,均基於以下版本:

  • IntelliJ IDEA:2020.1.2旗艦版

正文

使用IDEA這么久,雖然之前時不時地的跟IDEA問題“交過手”,但真正促使我決定寫此專欄的原因還是源自於前兩天使用IDEA啟動Spring Boot程序時的這個報錯:

Error running 'Application': Command line is too long. Shorten command line for Application or also for Spring Boot default configuration.


說實話這個錯誤我前所未見,看起來還蠻有意思,因此決定研究一番。這不,把研究結果分享給大家,信息共享。

為了解釋好這個問題,我們得先來做些功課,知曉寫概念。


控制台首行路徑

在IDEA里,你每次啟動一個main函數時,控制台第一行輸出的“日志”稱作為:控制台首行路徑。這里,我運行一個最最最簡單的程序,看看它長啥樣,程序如下:

public class Application {

    public static void main(String[] args) {
        System.out.println("Hello world");
    }
}

運行程序,控制台輸出如下截圖:

相信小伙伴每天都能看見它但大概率不會注意到它,我也不例外。你想不到的是,恰巧這行“日志”就成為了本文今天的主角,會圍繞它來展闡述。

特別說明:如果你是用外置tomcat驅動應用啟動的話效果不是這樣子的。因為它使用的是tomcat的腳本來啟動,所以首行日志形如這樣:D:\developer\apache-tomcat-9.0.34\bin\catalina.bat run


首行路徑內容

知道了什么叫首行路徑,那么它的內容才是我們要關心的。如上截圖中,細心的你會發現最后是...省略號,因此內容絕不止你現在看到的那么簡單。你可以鼠標點擊一下,展開全部內容,截圖如下:

一行實在太長了,無法橫向截圖全部展示出來,因此我把它復制出來放在文本編輯器中查看:

這個截圖是一行哦(只是我在文本編輯器了自動折行了而已),仍舊不能看到全部內容,因為字數真的太多了,總字數統計如下:

僅僅一行,字數超過26000個。咋舌吧:第一行控制台“日志”竟然輸出了超過2.6w個字符。從內容結構上來看,這是一個command命令:調用java.exe程序啟動一個java進程的命令


為何啟動拋錯Command line is too long

99.99%的情況下,你可以在IDEA里正常啟動你的應用,即使首行路徑很長很長。但是直到當我啟動我的這個Spring Boot應用時,彈出紅色提示:

直接禁止了我的running運行。提示內容中文釋義為:運行“Application”時出錯:命令行太長。縮短應用程序或Spring Boot默認配置的命令行。我相信如果你也是第一次見到此case,表情和我一樣是這樣的:

main方法都啟不動了,那還得了。遇到這種情況,我只能使用百度大法(谷歌大法)了:

一看能搜出這么多結果,我也就不慌了,按照“教程”很容易的把問題解決了。另外呢,通過此次搜索到的結果聊兩句題外話:

  1. 雖然Result Count不少,但是我發現實質上內容幾乎一毛一樣,真乃天下文章一大抄
  2. 訪問量並不代表文章質量高,只是它剛好命中了關鍵字而已,比如標題黨

我得出如此感悟,也是促使我寫本文的原因之一。因為A哥的文章一貫如此,是有些B格的。接下來以點帶面,把這部分內容幫大家展開展開,解決問題並非最終目的,而是為了:記得牢,能裝x,一切為了加薪。


原因分析

出現此問題的直接原因是:IDEA集成開發環境運行你的“源碼”的時候(注意是源碼基礎上運行,並非打好的jar包哦),是通過命令(首行那個非常非常長的)來啟動Java進程的。這個命令主要包含兩大部分:

  1. vm/程序參數。也就是你看到的那些-XX -D等參數,這部分理論上可以無限長但實際上一般不會太長
  2. -classpath參數,它用於指定運行時jar包路徑(因為jar包理論上是可以在任何地方的),這部分可能性就多了

關鍵就在於-classpath參數,它可以非常長,你依賴的jar包越多此路徑就越長;你的base基路徑越長它就越長;倘若你還要做復雜的Junit單元測試,那加入的jar包就更多長度可能就越長嘍。總的來說:此part是很有可能超長從而導致Command line is too long現象的。

如果類路徑太長(可能性大),或者您有許多VM參數(可能性小),則無法啟動該程序。原因是大多數操作系統都有命令行長度限制。在這種情況下,IntelliJ IDEA將提供嘗試縮短類路徑的能力。


IDEA老版本方案

針對此問題,在之前版本(確切的說是2017.3之前的版本),需要通過XML文件配置來解決:找到工程下的.idea/workspace.xml這個文件,添加如下項:

<component name="PropertiesComponent">
	...
	<!-- 這句是你需要添加的項 -->
	<property name="dynamic.classpath" value="true" />
	...
</component>

再次啟動程序發現問題解決。我有理由相信,在這個時間節點上應該沒有人用這么古老的版本了吧,但你在網上搜的文章大多數都還是這種解決方案,因此請務必注意甄別哦(2017.3以后的版本請參照下面方案解決)。

所以我不是說了麽,任何不指定版本的解決方案、源碼分析文章都是不太負責任的。作為一個程序員,應該適當提高自己的版本意識


IDEA新版本方案:命令行縮短器

在IDEA的2017.3版本中提供了一項新特性:命令行縮短器。旨在用來解決此類問題,也就是說從此版本開始,不再需要通過XML文件來編輯IDE的設置那么麻煩了,而是直接在界面操作即可:

最初,IntelliJ IDEA嘗試將長類路徑寫入文本文件(這意味着應用程序是中間類加載器)。但是不幸的是,這不適用於某些框架,例如JMock。然后,IntelliJ IDEA嘗試使用或多或少的標准方法,即將長類路徑打包到classpath.jar中。不幸的是,對於其他一些框架,這也不起作用。

總結:這兩種方案都不是100%完美的,具體情況具體分析

從上對話框中可以看到IDEA一共提供了三種命令行縮短器供你選擇:

  1. none。這是默認選項。IDE不會縮短長類路徑。如果命令行超出操作系統限制,則IDEA將無法運行您的應用程序
  2. jar manifest。IDE通過臨時classpath.jar傳遞長類路徑。原始類路徑在MANIFEST.MF中定義為classpath.jar中的類路徑屬性
  3. classpath file。IDE將把長類路徑寫入文本文件

jar manifest方式

選擇此種方式,運行測試程序,首行全部內容展示如下:

D:\developer\jdks\1.8.0_241\bin\java.exe -XX:TieredStopAtLevel=1 -noverify 
	-Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote 
	-Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain 
	-Dspring.application.admin.enabled=true 
	"-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2020.1.1\lib\idea_rt.jar=5975:C:\Program Files\JetBrains\IntelliJ IDEA 2020.1.1\bin" -Dfile.encoding=UTF-8 
	-classpath C:\Users\xxx\AppData\Local\Temp\classpath1199511058.jar 
	com.xxx.Application

區別主要在於-classpath這一行,它不再是把所有jar的路徑展示出來,而是“封裝”到了一個jar文件里,這一下子讓命令長度大幅減少,能夠100%保證不會超長了,所以啟動也就不會報錯嘍。

另外,在IDEA里你直接單擊此jar路徑是可以預覽器內容的(真貼心):

當然,你也可以在你磁盤里找到此jar文件,然后查看其內容(說明:請確保hold住線程了再去找對應文件,否則臨時文件是線程結束后就刪除了的):

特別強調:我在實踐過程中,使用此種方式出現過jar包沒有被加載進來的情況,在此提醒各位,若你也有類似現象發生,請切換成使用classpath file方式吧。

畢竟官方也說了:這兩種路徑縮短方式,對某些框架可能存在不兼容情況,just可能而已哦~


classpath file方式

選擇此種方式,運行測試程序,首行全部內容展示如下:

D:\developer\jdks\1.8.0_241\bin\java.exe -XX:TieredStopAtLevel=1 -noverify 
	-Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote 
	-Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain 
	-Dspring.application.admin.enabled=true 
	"-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2020.1.1\lib\idea_rt.jar=5975:C:\Program Files\JetBrains\IntelliJ IDEA 2020.1.1\bin" -Dfile.encoding=UTF-8 
	-classpath C:\Users\xxx\AppData\Local\Temp\idea_classpath921151059
	com.xxx.Application

有了上面的描述,這個就不用A哥贅述了。



擴展知識:windows系統命令最大長度

這屬於擴展知識,延伸閱讀內容。

既然已經知道出現此問題的原因是命令超長了而“報錯”,A哥就想那windows命令最長允許多少字符呢?帶着這個問題,我開始了一番苦心尋找,最后終於在windows官網找到了我想要的答案。地址在這:https://docs.microsoft.com/zh-cn/windows/win32/api/processenv/nf-processenv-setenvironmentvariablea?redirectedfrom=MSDN

在Windows上,命令行長度最大為32767個字符(和shell長度、命令提示符長度的區別)。當提供足夠大的類路徑時,將違反此限制,並且Windows拒絕執行該命令並拋出錯誤代碼87。推薦的解決方案有如下兩種:

  1. 將所有jar復制到一個公共文件夾,例如c:\jars,然后將其包括在內。這樣,每個jar都有一個短路徑,即c:\jars(而不是長路徑c:\program files\app\lib\app-jar1.jar),並且應該可以將這個路徑們控制在38kb之內
  2. 如果步驟1不起作用,則可以將單個jar提取到一個文件夾中,並創建一個包含所有提取文件的新jar。這樣就只需要引入這個新jar就可以了

這是兩種解決問題的思想:短路徑方式(簡單高效)和打包方式(100%能解決問題)

別問A哥為毛只給出windows的最大長度,沒有Mac的嗎?我只能說,我很窮所以用的是windows本,Mac的我不關心😄


思考題

今日份思考題比較簡單

  1. 為毛你的Spring Boot應用在生產環境下從來不用擔心出現Command line is too long這種錯誤?
  2. 有哪些有效的方式可以避免你的開發環境出現此問題?

總結

IDEA踩坑系列第一篇到這就結束了,算不算精彩呢?我個人覺得還可以😄。此專欄后續將不定期的更新,除了我自己准備外,同時也非常歡迎各位小伙伴能把平時遇到的IDEA遇到的棘手問題反饋給我(最好有解決方案哦),咱們一起把這個事做好,也算造福於大家嘛,畢竟我一個人碰見的case實則有限,有建議的可以下方掃碼加我好友私聊我。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM