Jib構建映象的問題分析(Could not find or load main class ${start-class})
問題簡述
通過Jib外掛將SpringBoot工程製作成Docker映象成功,但是執行映象的時候報錯(Could not find or load main class ${start-class}),今天來一起分析這個問題,希望能幫讀者跳過小坑。
關於Jib外掛
在Maven工程中可以使用Jib外掛將當前Java工程構建成Docker映象,詳情請參考:
環境資訊
- 作業系統:macOS Mojave 10.14.6 (18G103)
- JDK:10.14.6 (18G103)
- Docker:10.14.6 (18G103)
- SpringBoot:2.1.8.RELEASE
- Jib外掛版本:1.6.1
原始碼下載
為了重現問題,我將出現問題的SpringBoot工程上傳到GitHub,地址和連結資訊如下表所示:
名稱 | 連結 | 備註 |
---|---|---|
專案主頁 | https://github.com/zq2599/blog_demos | 該專案在GitHub上的主頁 |
git倉庫地址(https) | https://github.com/zq2599/blog_demos.git | 該專案原始碼的倉庫地址,https協議 |
git倉庫地址(ssh) | [email protected]:zq2599/blog_demos.git | 該專案原始碼的倉庫地址,ssh協議 |
</br>
這個git專案中有多個資料夾,本章的應用在jib-error-demo資料夾下,如下圖紅框所示:
問題:
- 在pom.xml檔案所在目錄執行命令<font color="blue">mvn clean compile -U</font>,映象可以構建成功,但是控制檯輸出了警告資訊,如下圖:
- 嘗試用此映象建立容器,行命令<font color="blue">docker run --name=test bolingcavalry/hellojib:0.0.1-SNAPSHOT</font>,報錯如下:
CN0014005932:~ zhaoqin$ docker run --name=test bolingcavalry/hellojib:0.0.1-SNAPSHOT
Error: Could not find or load main class ${start-class}
- <font color="blue">docker ps -a</font>檢視容器資訊如下,只能看到狀態是"退出",別的沒啥了:
CN0014005932:~ zhaoqin$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d618f6588821 bolingcavalry/hellojib:0.0.1-SNAPSHOT "java -Xms4g -Xmx4g …" 4 minutes ago Exited (1) 4 minutes ago test
- 不甘心,用命令<font color="blue">docker ps -a --no-trunc</font>檢視未截斷的容器資訊:
CN0014005932:~ zhaoqin$ docker ps -a --no-trunc
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d618f6588821f00d3bd0b67a85ff92988b90dfff710370c9d340d5c544c550af bolingcavalry/hellojib:0.0.1-SNAPSHOT "java -Xms4g -Xmx4g -cp /app/resources:/app/classes:/app/libs/* ${start-class}" 7 minutes ago Exited (1) 7 minutes ago test
- 這次有新發現,容器啟動時執行命令是<font color="blue">java -Xms4g -Xmx4g -cp /app/resources:/app/classes:/app/libs/* ${start-class}</font>,怪哉!這個<font color="red">${start-class}</font>是什麼?我們來看一個正常映象的啟動命令:
java -Xms4g -Xmx4g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.jiberrordemo.JibErrorDemoApplication
如上所示,<font color="blue">com.bolingcavalry.jiberrordemo.JibErrorDemoApplication</font>是main方法所在類,此命令可以正常執行JibErrorDemoApplication類的main方法; 6. 小結問題:容器啟動時執行java命令,把<font color="blue">${start-class}</font>作為引數傳給java,導致java無法處理此引數,所以程序報錯,導致容器退出;
問題原因
此問題的原因很簡單:<font color="blue">java工程中帶有main方法的類不止一個</font>,去檢視jib-error-demo工程的程式碼,發現Utils.java中果然有個main方法:
public class Utils {
public static String time(){
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()).toString();
}
public static void main(String[] args){
System.out.println(time());
}
}
將上述main方法刪除掉,再構建映象並執行容器,證實問題已經解決。
另一種解決問題的方法
如果不想動Utils類的程式碼(也許jar包中某個類帶有main方法),請開啟pom.xml檔案,在jib外掛的配置中增加<font color="blue">mainClass</font>節點,節點內容是指定的class類,如下圖紅框所示: 經過上面的設定,問題也可以解決。
接下來,如果您有興趣瞭解更深層次的原因,咱們一起來深度探險吧。
查詢問題
- 這個問題在Jib的官方GitHub上是有記錄的,先看第一條,地址是:https://github.com/GoogleContainerTools/jib/issues/1601 ,如下圖紅框所示,同樣的問題,最後issue的發起人自己關閉了這個issue,因為他發現這自己的專案中有兩個帶有main方法的類:
- 再來看看這個issue, https://github.com/GoogleContainerTools/jib/issues/170 ,Jib的作者Q Chen推測是Spring將<font color="blue">${start-class}</font>這個字串設定為Main-Class屬性的值(個人感覺,這裡說的Spring應該是spring boot的mave外掛吧),於是Jib外掛在使用Main-Class的值得時候,拿到的就是<font color="blue">${start-class}</font>這個字串了:
- 170這個issue的後續情節很有意思,Jib作者Q Chen對這個問題也很糾結,如果Java工程中發現了多個帶有main方法的類,Jib究竟該如何處理呢?Q Chen最後決定輸出警告,如下圖:
- 一起來看看這段程式碼吧,也就是上圖中#288,地址是:https://github.com/GoogleContainerTools/jib/pull/228/files/c8757e1f9ea47edd78df18142de7836a68f22034 ,如果mainClass不像一個class類的名稱,就輸出警告,這個邏輯在Gradle和Maven外掛中都寫入了:
- 最後一個問題:上面程式碼中的mainClass從哪來的?開啟上圖的原始碼,地址是:https://github.com/GoogleContainerTools/jib/blob/c8757e1f9ea47edd78df18142de7836a68f22034/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java ,如下圖紅框,從方法名可以推測,該值來自構建SpringBoot工程的maven外掛,所以前面Q Chen提到main-class變數的值是Spring修改的,應該是來自這段程式碼: 此時的您,如果依然意猶未盡,咱們再來鞏固一下SpringBoot的start-class
關於start-class
- 熟悉SpringBoot的同學其實對<font color="blue">${start-class}</font>並不陌生,當工程中多個類中都有<font color="blue">main</font>方法時,使用該引數來指定SpringBoot的啟動類;
- 先看SpringBoot官方文件熟悉一下<font color="blue">start-class</font>,地址是:https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/ ,下圖內容比較關鍵:我們設定的啟動類被指定到<font color="blue">Start-Class</font>屬性中,而<font color="blue">Main-Class</font>屬性變成了<font color="blue">org.springframework.boot.loader.JarLauncher</font>,這才是SpringBoot真正的啟動類:
- 如下圖,這是個補充說明,<font color="blue">Main-Class</font>屬性的值被轉移到<font color="blue">Start-Class</font>屬性這個動作,是maven外掛在構建jar的時候做的:
- 所以start-class的值是來自main-class,再看main-class的值從哪裡來,如下圖紅框所示,maven外掛會去查詢帶有<font color="blue">public static void main(String[] args)</font>的類: 至此,Jib構建的映象問題分析完畢,一個小小的問題引發了這麼多學習和探索,雖然有點費時間,但是可以讓人再次感受到"技術是相通的"感覺,不知道您有沒有這種感覺呢?
歡迎關注我的公眾號:程式設計師欣宸
相關推薦
Jib構建映象的問題分析(Could not find or load main class ${start-class})
問題簡述 通過Jib外掛將SpringBoot工程製作成Docker映象成功,但是執行映象的時候報錯(Could not find
Linux終端運行java源碼出錯——Error: Could not find or load main class [duplicate]
終端 -o erro main spa class文件 img not find https Linux終端中運行.class文件出錯 Linux終端運行java源碼出錯——Error: Could not find or load main class [duplicat
hadoop 3.1.1 Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster
name ado org 3.1.1 div 9.png per mapred 技術分享 啟動hdfs後執行share目錄中自帶的mapreduce程序時報如下錯誤 找到$HADOOP_HOME/etc/mapred-site.xml,增加以下配置 1 <p
在idea裡執行maven專案出現:Error: Could not find or load main class com.xxx.xxxx
原因分析:maven專案在執行時找不到主類,也就是專案啟動類找不到。可以嘗試以下方法。 思路:java檔案必須經過compile才會變成.class檔案,找不到.class檔案就是由於沒有經過編譯導致的。 可能是由於對maven專案執行了mvn clean命令,沒有執行mvn compile
flume啟動報錯 Could not find or load main class org.apache.flume.node.Application
修改flume的資料夾名稱後,啟動flume可能會失敗,錯誤資訊如下: Error: Could not find or load main class org.apache.flume.node.Application 這個是因為環境變數的問題。 export看一下是不是有個FLUME_HOME的
zookeeper SolrCloud 叢集配置 Error: Could not find or load main class org.apache.solr.cloud.ZkCLI
搭建SolrCloud叢集 把solrhome中的配置檔案上傳到zookeeper叢集。使用zookeeper的客戶端上傳。 客戶端命令位置:/root/solr-4.10.3/example/scripts/cloud-scripts 執行命令 ./zk
搭建SolrCloud叢集Could not find or load main class org.apache.solr.cloud.ZkCLI
搭建SolrCloud叢集 報錯解決方案 1、把solrhome中的配置檔案上傳到zookeeper叢集。 //1、進入cloud-scripts目錄下 (以下IP為示例,請根據自己實際配置填寫) cd /root/solr-4.10.3/example/scripts/cloud-
報錯:Error: Could not find or load main class org.apache.flume.tools.GetJavaProperty
輸入flume-ng version 啟動flume時報錯Error: Could not find or load main class org.apache.flume.tools.GetJavaProperty,但似乎已經啟動. 這時我們可以去hbase中修改hbase-e
java報錯-找不到或無法載入主類(Error: Could not find or load main class)
文章目錄 CLASSPATH配置問題 package問題 解決方法1:刪除package宣告 解決方法2:指定包名 比如說test.java package test; public
Sqoop找不到主類 Error: Could not find or load main class org.apache.sqoop.Sqoop
最近由於要使用Sqoop來到出資料到hdfs,可是發現Sqoop1.4.5跟hadoop2.X不相容,需要對Sqoop1.4.5進行編譯,編譯的具體方法見:http://my.codeweblog.com/AlbertHa/blog/318551 如果一切都順利的話需要就不會遇到什麼問題,但是有一個問題一直
Linux 下 Error: Could not find or load main class Hello
在linux下寫了一個非常簡單的Hello world程式,編譯執行竟然報錯:Error: Could not find or load main class Hello 最後發現是CLASSPATH的問題。 主要在環境變數這塊: export JAVA_HOME=/u
搭建SolrCloud: Error: Could not find or load main class org.apache.solr.cloud.ZkCLI
【./zkcli.sh:line 13: unzip: command not found Error: Could not find or load main class org.apache
Travis CI Could not find or load main class org.gradle.wrapper.GradleWrapperMain 錯誤
問題 在 Travis CI 編譯的時候出現 Error: Could not find or load main
解決Qt編譯動態連結庫could not find or load the Qt platform plugin "windows" in.問題
最近用Qt5做了一個專案的介面,在編譯成可執行檔案EXE之後,執行檔案,提示: This application failed to start because it could not find or load the Qt platfo rm plugin "windows" in "".
This application failed to start because it could not find or load the Qt platform plugin windows
Qt 程式報錯 This application failed to start because it could not find or load the Qt platform plugin “windows” 如下圖 今天遇到一個很奇怪的問題,Qt應用程
板子執行qt程式could not find or load the Qt platform plugin "xcb"
交叉編譯qt5後放板子上執行應用程式,./qtest 出錯could not find or load the Qt platform plugin "xcb" ls /usr/local/qt5-arm/plugins/platforms/ libqlinuxfb.so
This application failed to start because it could not find or load the Qt platforms plugins
由於一直在linux下操作,今天Qt移植平臺的時候導致.exe可執行檔案一直執行不起來,提示缺少某些dll庫,這個問題解決起來簡單(直接去qt原始碼裡面查詢對應庫新增到可執行檔案目錄就行),但是之後
could not find or load the Qt platform plugin windows的解決方法
VS+Qt5環境下建立一個Qt工程,在本機執行沒問題,可是把.exe和用到的.dll打包發到別人電腦上卻執行不了,報錯如下: 為什麼會這樣?這是因為程式執行需要Qt本身的一些dll,把這些缺失的dll補上就可以了。 需要注意的是:一般遇到這個報錯,是缺少plugins
【qt錯誤】This application failed to start because it could not find or load
qt釋出exe無法執行,提示plugin windows錯誤 This application failed to start because it could not find or load the Qt platform plugin “window
[pyqt5]解決could not find or load the Qt platform plugin windows
在PyQt5+python3+pycharm開發環境配置時,遇到了This application failed to start because it could not find or load