SpringBoot直接启动与jar包启动的不同

SpringBoot作为Java后台开发常用的技术点之一,相信很多人不陌生,但是其中的一些有趣的点,很多人并不一定都了解。

首先,在springbbot程序主函数处,加上一句控制台打印消息,打印出加载当前应用的入口函数所在类的加载器信息。
Springboot启动类

直接启动

在开发工具中,直接启动该应用,观察到如下所示:
直接启动
对类加载器有所了解的应该知道,输出的含义为:系统类/应用类加载器

Jar包的方式启动

通过maven或者gradle等方式对程序进行打包,生成可运行的Jar包,然后通过java -jar xx.jar的方式启动,观察到如下所示:
jar包的方式启动
通过Jar包的方式运行的加载器为:LaunchedURLClassLoader,造成两者不同的原因是什么呢?

Jar包的结构

可执行Jar也是一种压缩包,使用压缩工具对其进行解压后,会得到如下所示的结构:
解压jar后的结构
META_INF目录下能看到MANIFEST.MF,该文件是打包时自动生成的,是
清单文件,内容大体如下:
MANIFEST.MF清单文件内容
其中Main-Class是Jar包启动的入口文件,找到该文件,然后分析执行流程或者通过断点的方式观察其执行的步骤,可以看到:

// step1(JarLauncher.java)
public static void main(String[] args) throws Exception {
	new JarLauncher().launch(args); // 跟踪launch()方法
}

// step2(Launcher.java)
protected void launch(String[] args) throws Exception {
	if (!isExploded()) {
		JarFile.registerUrlProtocolHandler();
	}
	// 跟踪createClassLoader(),该函数返回的结果就是jar包启动方式的加载器
	ClassLoader classLoader = createClassLoader(getClassPathArchivesIterator());
	String jarMode = System.getProperty("jarmode");
	String launchClass = (jarMode != null && !jarMode.isEmpty()) ? JAR_MODE_LAUNCHER : getMainClass();
	launch(args, launchClass, classLoader);
}

// step3(ExecutableArchiveLauncher.java)
@Override
protected ClassLoader createClassLoader(Iterator<Archive> archives) throws Exception {
	List<URL> urls = new ArrayList<>(guessClassPathSize());
	while (archives.hasNext()) {
		urls.add(archives.next().getUrl());
	}
	if (this.classPathIndex != null) {
		urls.addAll(this.classPathIndex.getUrls());
	}
	// 创建类加载器
	return createClassLoader(urls.toArray(new URL[0]));
}

// step4(Launcher.java)
protected ClassLoader createClassLoader(URL[] urls) throws Exception {
	 // 此处返回类加载器
	return new LaunchedURLClassLoader(isExploded(), getArchive(), urls, getClass().getClassLoader());
}

通过如上的分析,可以知道加载Jar包的类加载器,以及其基本的加载流程。而直接启动的方式会直接运行入口函数,main函数在类路径下,因此直接启动的方式是系统类加载器加载的。

想要更加深入的了解Jar包的执行流程,可以使用java -agentlib:jdwp命令来进行断点调试。该命令的具体的使用方法请自行搜索。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值