通过jib插件将springboot工程制作成docker镜像成功,但是运行镜像的时候报错(could not find or load main class ${start-class}),今天来一起分析这个问题,希望能帮读者跳过小坑。
在maven工程中可以使用jib插件将当前java工程构建成docker镜像,详情请参考:
为了重现问题,我将出现问题的springboot工程上传到github,地址和链接信息如下表所示:
名称 | 链接 | 备注 |
---|---|---|
项目主页 | https://github.com/zq2599/blog_demos | 该项目在github上的主页 |
git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
这个git项目中有多个文件夹,本章的应用在jib-error-demo文件夹下,如下图红框所示:
cn0014005932:~ zhaoqin$ docker run --name=test bolingcavalry/hellojib:0.0.1-snapshot error: could not find or load main class ${start-class}
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
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
java -xms4g -xmx4g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.jiberrordemo.jiberrordemoapplication
如上所示,com.bolingcavalry.jiberrordemo.jiberrordemoapplication是main方法所在类,此命令可以正常运行jiberrordemoapplication类的main方法;
此问题的原因很简单:java工程中带有main方法的类不止一个,去查看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插件的配置中增加mainclass节点,节点内容是指定的class类,如下图红框所示:
经过上面的设置,问题也可以解决。
接下来,如果您有兴趣了解更深层次的原因,咱们一起来深度探险吧。
最后一个问题:上面代码中的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的值是来自main-class,再看main-class的值从哪里来,如下图红框所示,maven插件会去查找带有public static void main(string[] args)的类:
至此,jib构建的镜像问题分析完毕,一个小小的问题引发了这么多学习和探索,虽然有点费时间,但是可以让人再次感受到"技术是相通的"感觉,不知道您有没有这种感觉呢?
如对本文有疑问, 点击进行留言回复!!
Java Class.forName()用法和newInstance()方法原理解析
网友评论