【死磕-第一篇】创建SpringApplication对象
导读
- 每次每次!!!!,面试就看spring的源码,各种视频笔记到处看一点,没有系统的从头到尾学习
- 这次!!,我一定要从main开始到结束,全部看完
1. 项目环境
版本
- spring-boot 2.3.0.RELEASE
项目pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
- 整个项目只引入了这一个依赖,从最常用的这个依赖来看springweb应用是如何启动的
项目代码
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
- 整个项目只有这样一个启动类,其余别的代码都没有,之后要是有测试的话,会加入一些代码来证明
2. 文章重点
- 此篇文章主要讲述了main函数启动,调用
SpringApplication.run(MainApplication.class, args);
- 这个函数中创建了一个SpringApplication对象,主要讲创建这个对象的构造函数干了什么
3. 源码解析(流程)
// 当前所在类:MainApplication.java (自己创建的)
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
// 调用SpringApplication 的静态 run方法
// 传入当前所在类,以及main方法中的args
SpringApplication.run(MainApplication.class, args);
}
}
- 跳转到 run静态函数内部
// 当前所在类:SpringApplication.java
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified source using default settings.
* 翻译:此静态方法可用于使用默认设置从指定源运行 SpringApplication
* @param primarySource the primary source to load
* 翻译:参数primarySource 主配置源
* @param args the application arguments (usually passed from a Java main method)
* 翻译:args 应用程序参数(通常从Java main方法中传递)
* @return the running {@link ApplicationContext}
* 翻译:返回运行中的 ApplicationContext
*/
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
- 跳转到run(new Class<?>[] { primarySource }, args) 内部
// 当前所在类:SpringApplication.java
/**
* Static helper that can be used to run a {@link SpringApplication} from the
* specified sources using default settings and user supplied arguments.
* @param primarySources the primary sources to load
* @param args the application arguments (usually passed from a Java main method)
* @return the running {@link ApplicationContext}
*/
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
- 此方法和上一个方法类似,这是这个方法可以传入多个primarySources
- 跳转到new SpringApplication(primarySources) 内部(不是 run(args) 内部)
// 当前所在类:SpringApplication.java
/**
* Create a new {@link SpringApplication} instance. The application context will load
* beans from the specified primary sources (see {@link SpringApplication class-level}
* documentation for details. The instance can be customized before calling
* {@link #run(String...)}.
*
* 翻译:创建一个SpringApplication的实例,这个程序的context将会加载beans 从具体的主配置源
* 这个实例可以定制化在调用之前
*
* @param primarySources the primary bean sources
*
* 翻译:primarySources是 主要bean的来源
*
* @see #run(Class, String[])
* @see #SpringApplication(ResourceLoader, Class...)
* @see #setSources(Set)
*/
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
- 跳转到
this(null, primarySources);
的内部
// 当前所在类:SpringApplication.java
/**
* Create a new {@link SpringApplication} instance. The application context will load
* beans from the specified primary sources (see {@link SpringApplication class-level}
* documentation for details. The instance can be customized before calling
* {@link #run(String...)}.
*
* 翻译:创建一个SpringApplication的实例,这个程序的context将会加载beans 从具体的主配置源
* 这个实例可以定制化在调用run(String...)之前
*
* @param resourceLoader the resource loader to use
*
* 翻译:resourceLoader 要使用的资源加载器
*
* @param primarySources the primary bean sources
*
* 翻译:primarySources 主配置源
*
* @see #run(Class, String[])
* @see #setSources(Set)
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 设置资源加载器
this.resourceLoader = resourceLoader;
// 断言判断:primarySources不能为null
Assert.notNull(primarySources, "PrimarySources must not be null");
// 设置主配置源
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 设置此程序是什么类型的(NONE,SERVLET,REACTIVE)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 设置初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 设置监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 设置主程序所在的class
this.mainApplicationClass = deduceMainApplicationClass();
}
4. 源码详细解析
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 设置资源加载器
this.resourceLoader = resourceLoader;
// 断言判断:primarySources不能为null
Assert.notNull(primarySources, "PrimarySources must not be null");
// 设置主配置源
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 4.1 设置此程序是什么类型的(NONE,SERVLET,REACTIVE)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 4.2 设置初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 4.3 设置监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 4.4 设置主程序所在的class
this.mainApplicationClass = deduceMainApplicationClass();
}
4.1 设置程序的类型
// 4.1 设置此程序是什么类型的(NONE,SERVLET,REACTIVE)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
- 跳转到
deduceFromClasspath()
内部
// WEBFLUX_INDICATOR_CLASS org.springframework.web.reactive.DispatcherHandler
// WEBMVC_INDICATOR_CLASS org.springframework.web.servlet.DispatcherServlet
// JERSEY_INDICATOR_CLASS org.glassfish.jersey.servlet.ServletContainer
// SERVLET_INDICATOR_CLASSES
// javax.servlet.Servlet
// org.springframework.web.context.ConfigurableWebApplicationContext
// deduceFromClasspath()
// 翻译:从Classpath推断此程序是什么类型的
static WebApplicationType deduceFromClasspath() {
// 如果
// 存在 DispatcherHandler
// && 不存在 DispatcherServlet
// && 不存在 ServletContainer
// 则 程序是 REACTIVE 类型
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
// 如果
// 不存在 Servlet
// || 不存在 ConfigurableWebApplicationContext
// 则 程序是 NONE 类型
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
// 以上都不成立 则 程序是 SERVLET 类型
return WebApplicationType.SERVLET;
}
- 跳转到
ClassUtils.isPresent
内部
// isPresent(String className, @Nullable ClassLoader classLoader)
// 翻译:根据传入的类名,在传入的类加载器中查找是否存在此类
public static boolean isPresent(String className, @Nullable ClassLoader classLoader) {
try {
// 根据类名在类加载器中查找
forName(className, classLoader);
return true;
}
catch (IllegalAccessError err) {
throw new IllegalStateException("Readability mismatch in inheritance hierarchy of class [" +
className + "]: " + err.getMessage(), err);
}
catch (Throwable ex) {
// Typically ClassNotFoundException or NoClassDefFoundError...
/**
* ClassNotFoundException 和 NoClassDefFoundError 的区别
* 详细解释:https://www.huaweicloud.com/articles/11967786.html
*/
return false;
}
}
- 跳转到
forName(className, classLoader)
内部
/**
* Replacement for {@code Class.forName()} that also returns Class instances
* for primitives (e.g. "int") and array class names (e.g. "String[]").
* Furthermore, it is also capable of resolving inner class names in Java source
* style (e.g. "java.lang.Thread.State" instead of "java.lang.Thread$State").
*
* 翻译:此方法对标于Class.forName(),同样也返回class的实例
* 对于int,String[] 这种也可以返回
* 对于内部类 可以 用java.lang.Thread.State 来替换 java.lang.Thread$State用于查找
*
* @param name the name of the Class
* @param classLoader the class loader to use
* (may be {@code null}, which indicates the default class loader)
* @return a class instance for the supplied name
* @throws ClassNotFoundException if the class was not found
* @throws LinkageError if the class file could not be loaded
* @see Class#forName(String, boolean, ClassLoader)
*/
public static Class<?> forName(String name, @Nullable ClassLoader classLoader)
throws ClassNotFoundException, LinkageError {
// 断言: name不能为空
Assert.notNull(name, "Name must not be null");
// 解决基本类型的获取,例如int,float,double,以及int[],float[],等等
Class<?> clazz = resolvePrimitiveClassName(name);
if (clazz == null) {
// 解决Integer,Double,以及异常,Byte, java.lang, Iterator等等常用的类型以及接口
clazz = commonClassCache.get(name);
}
if (clazz != null) {
return clazz;
}
// "java.lang.String[]" style arrays
// 以[] 结尾的
if (name.endsWith(ARRAY_SUFFIX)) {
// 移除名字中的[], java.lang.String[] -》 java.lang.String
String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length());
// 获取 java.lang.String 在类加载器中,因为没有java.lang.String[]类型, 如果是[][]则会再次调用
Class<?> elementClass = forName(elementClassName, classLoader);
// 返回的名字竟然是调用Array的静态实例化方法然后获取这个实例的class获得,虽然传入的是0,但是也太奇怪了
return Array.newInstance(elementClass, 0).getClass();
}
// "[Ljava.lang.String;" style arrays
if (name.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && name.endsWith(";")) {
String elementName = name.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), name.length() - 1);
Class<?> elementClass = forName(elementName, classLoader);
return Array.newInstance(elementClass, 0).getClass();
}
// "[[I" or "[[Ljava.lang.String;" style arrays
// [[L代表 String[][], Integer[][]
// [[I代表 int[][]
// [[F代表 float[][]
if (name.startsWith(INTERNAL_ARRAY_PREFIX)) {
String elementName = name.substring(INTERNAL_ARRAY_PREFIX.length());
Class<?> elementClass = forName(elementName, classLoader);
return Array.newInstance(elementClass, 0).getClass();
}
ClassLoader clToUse = classLoader;
if (clToUse == null) {
// 获取默认的类加载器
clToUse = getDefaultClassLoader();
}
try {
// 根据名称从指定类加载器中获取
return Class.forName(name, false, clToUse);
}
catch (ClassNotFoundException ex) {
// 特别的去处理xxx.xxxx.xxxx 这种类,但实际在类加载器中存在的是 xxx.xxxx$xxxx 这种类形式的存在
// 获取最后一个点的位置
int lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR);
if (lastDotIndex != -1) {
// 如果找的到的话,就将最后一个点换成$
String innerClassName =
name.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR + name.substring(lastDotIndex + 1);
try {
// 重新获取
return Class.forName(innerClassName, false, clToUse);
}
catch (ClassNotFoundException ex2) {
// Swallow - let original exception get through
}
}
throw ex;
}
}
- 跳转到
getDefaultClassLoader
/**
* Return the default ClassLoader to use: typically the thread context
* ClassLoader, if available; the ClassLoader that loaded the ClassUtils
* class will be used as fallback.
*
* 翻译:返回一个默认的类加载器去使用:通常是此线程的类加载器,如果有的话;加载ClassUtils类的类加载器将会作为后备
*
* <p>Call this method if you intend to use the thread context ClassLoader
* in a scenario where you clearly prefer a non-null ClassLoader reference:
* for example, for class path resource loading (but not necessarily for
* {@code Class.forName}, which accepts a {@code null} ClassLoader
* reference as well).
*
* 翻译:如果你打算在一个场景中使用线程上下文的ClassLoader,你显然更喜欢一个非空的ClassLoader引用,请调用此方法
* :例如,对于类的路径资源加载,(但不一定用于 Class.forName, 这也接受一个null的ClassLoader)
*
* @return the default ClassLoader (only {@code null} if even the system
* ClassLoader isn't accessible)
* @see Thread#getContextClassLoader()
* @see ClassLoader#getSystemClassLoader()
*/
@Nullable
public static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
// 返回此线程的类加载器
cl = Thread.currentThread().getContextClassLoader();
}
catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back...
}
// 如果是null
if (cl == null) {
// No thread context class loader -> use class loader of this class.
// 获取 ClassUtils类 加载的类加载器
cl = ClassUtils.class.getClassLoader();
if (cl == null) {
// getClassLoader() returning null indicates the bootstrap ClassLoader
try {
// 获取系统的类加载器
cl = ClassLoader.getSystemClassLoader();
}
catch (Throwable ex) {
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
}
}
}
return cl;
}
- 跳转返回
deduceFromClasspath()
内部
deduceFromClasspath()
可以理解为就是从各种类加载中获取指定的类,如果有或者没有此类来判断是什么类型的应用
4.2 设置初始化器
// 4.2 设置初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
- 跳转到
getSpringFactoriesInstances(ApplicationContextInitializer.class)
内部
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
// 可以根据类型以及参数类型来获取指定的类实例
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
- 跳转到
getSpringFactoriesInstances(type, new Class<?>[] {});
内部
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取加载器,底层逻辑是先获取resourceLoader的类加载器,没有的话然后用ClassUtils.getDefaultClassLoader();获取默认的类加载器
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
// 根据类型获取spring.factories中符合的类名
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 根据以上获取的类名创建类的实例
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 将实例进行排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
- 跳转到
SpringFactoriesLoader.loadFactoryNames(type, classLoader)
内部
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
// 获取传入的class的name
String factoryTypeName = factoryType.getName();
// 从spring.factories中获取指定的类型,如果没有的话,返回一个空List
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
- 跳转到
loadSpringFactories(classLoader)
内部
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
// 从缓存中获取类加载器
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
// 缓存中没有类加载器的话
// FACTORIES_RESOURCE_LOCATION META-INF/spring.factories
// 使用指定类加载器获取所有包中的META-INF/spring.factories
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
// 从指定位置加载 Properties
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
// 遍历 Properties 中的键值对
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
// 将spring.factories中的键值对结果以类加载器为key存入缓存中,以便下次调用直接从缓存中读取
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
- 返回
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
- 跳转到
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
内部
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
// 从类加载器中获取指定的类
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
// instanceClass 是不是 type的子类
Assert.isAssignable(type, instanceClass);
// 根据参数获取此类的构造器
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
// 根据传入的构造器对象以及构造器所需的参数创建一个实例
T instance = (T) BeanUtils.instantiateClass(constructor, args);
// 将创建好的实例添加到集合中
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
-
最后将返回结果给
setListeners()
-
跳转到
setInitializers
内部
/**
* Sets the {@link ApplicationContextInitializer} that will be applied to the Spring
* {@link ApplicationContext}.
*
* 翻译:设置多个ApplicationContextInitializer,这会施加到spring ApplicationContext 中
*
* @param initializers the initializers to set
*/
public void setInitializers(Collection<? extends ApplicationContextInitializer<?>> initializers) {
this.initializers = new ArrayList<>(initializers);
}
- 接着就
setListeners
- 其流程和
setInitializers
类似,不同的地方在于,他们从spring.factories中获取的key不同,setListerners
获取的是 ApplicationListener
- 最后也将获取到的类实例化,然后设置到springApplication中
/**
* Sets the {@link ApplicationListener}s that will be applied to the SpringApplication
* and registered with the {@link ApplicationContext}.
*
* 翻译: 设置 多个ApplicationListener, 这将会施加到SpringApplication 和 注册到ApplicationContext中
*
* @param listeners the listeners to set
*/
public void setListeners(Collection<? extends ApplicationListener<?>> listeners) {
this.listeners = new ArrayList<>(listeners);
}
- 最后来到了构造器的最后一步
// 设置主程序类
this.mainApplicationClass = deduceMainApplicationClass();
- 跳转到
deduceMainApplicationClass
内部
private Class<?> deduceMainApplicationClass() {
try {
// 创建一个运行异常获取他的方法调用栈的信息
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
// 循环遍历栈,判断哪个栈的方法名是main,返回此方法的class
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
5. 总结
重点介绍了哪些方法
- SpringApplication(ResourceLoader resourceLoader, Class<?>… primarySources)
- springApplication构造器
- ClassUtils.isPresent
- ClassUtils工具类方法,isPresent 用于判断是否存在此类
- SpringFactoriesLoader.loadFactoryNames
- 用于获取spring.factories中的值
- ClassUtils.getDefaultClassLoader
- 用于加载默认的ClassLoader
6.补充
ClassLoader.getSystemClassLoader() 是怎么运行的
/**
* Returns the system class loader for delegation. This is the default
* delegation parent for new <tt>ClassLoader</tt> instances, and is
* typically the class loader used to start the application.
*
* 翻译: 此方法返回系统类加载器,这个加载器是使用 ClassLoader 创建的加载器的默认父加载器,它通常被用来启动应用程序。
* 简单的说就是继承ClassLoader的加载器,默认的构造器函数(没有传入父加载器)是调用此函数作为父加载器的
*
* <p> This method is first invoked early in the runtime's startup
* sequence, at which point it creates the system class loader and sets it
* as the context class loader of the invoking <tt>Thread</tt>.
*
* 翻译:在程序早期运行的时候,此方法将会被第一次执行。当此方法被执行的时候,程序会创建系统类加载器并将其设置其调用该方法
* 父类加载器
* <p> The default system class loader is an implementation-dependent
* instance of this class.
* 翻译:这个系统类加载器是依赖于实现的一个类的实例,(即AppClassloader是抽象类ClassLoader类的一个实现,系统类加载器是这个
* 实现类的一个实例)。
*
* <p> If the system property "<tt>java.system.class.loader</tt>" is defined
* when this method is first invoked then the value of that property is
* taken to be the name of a class that will be returned as the system
* class loader. The class is loaded using the default system class loader
* and must define a public constructor that takes a single parameter of
* type <tt>ClassLoader</tt> which is used as the delegation parent. An
* instance is then created using this constructor with the default system
* class loader as the parameter. The resulting class loader is defined
* to be the system class loader.
* 翻译:如果系统的环境变量 java.system.class.loader 在此方法第一次执行之前被设置的话,这个属性的值代表的ClassLoader将会
* 被作为指定的系统类加载器,这个被指定的系统类加载器要求提供一个公有的接收一个ClassLoader参数的构造方法,这个CLassLoader会
* 被作为此类的父类加载器。这个类的加载器实例会被默认的系统类加载器创建,返回的系统类加载器就是系统类加载。
*
* <p> If a security manager is present, and the invoker's class loader is
* not <tt>null</tt> and the invoker's class loader is not the same as or
* an ancestor of the system class loader, then this method invokes the
* security manager's {@link
* SecurityManager#checkPermission(java.security.Permission)
* <tt>checkPermission</tt>} method with a {@link
* RuntimePermission#RuntimePermission(String)
* <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
* access to the system class loader. If not, a
* <tt>SecurityException</tt> will be thrown. </p>
*
* @return The system <tt>ClassLoader</tt> for delegation, or
* <tt>null</tt> if none
*
* @throws SecurityException
* If a security manager exists and its <tt>checkPermission</tt>
* method doesn't allow access to the system class loader.
*
* @throws IllegalStateException
* If invoked recursively during the construction of the class
* loader specified by the "<tt>java.system.class.loader</tt>"
* property.
*
* @throws Error
* If the system property "<tt>java.system.class.loader</tt>"
* is defined but the named class could not be loaded, the
* provider class does not define the required constructor, or an
* exception is thrown by that constructor when it is invoked. The
* underlying cause of the error can be retrieved via the
* {@link Throwable#getCause()} method.
*
* @revised 1.4
*/
@CallerSensitive
public static ClassLoader getSystemClassLoader() {
// 初始化系统类加载器
initSystemClassLoader();
if (scl == null) {
return null;
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
- 进入
initSystemClassLoader()
内部
private static synchronized void initSystemClassLoader() {
// sclSet:标识系统类加载器是否被加载
if (!sclSet) {
if (scl != null)
throw new IllegalStateException("recursive invocation");
// 获取launcher的实例
sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
if (l != null) {
Throwable oops = null;
// 获取launcher的实例中 类加载器
scl = l.getClassLoader();
try {
scl = AccessController.doPrivileged(
new SystemClassLoaderAction(scl));
} catch (PrivilegedActionException pae) {
oops = pae.getCause();
if (oops instanceof InvocationTargetException) {
oops = oops.getCause();
}
}
if (oops != null) {
if (oops instanceof Error) {
throw (Error) oops;
} else {
// wrap the exception
throw new Error(oops);
}
}
}
sclSet = true;
}
}
- 进入
Launcher.java
内部
public class Launcher {
private static Launcher launcher = new Launcher();
...
public Launcher() {
Launcher.ExtClassLoader var1;
try {
// 创建一个 ExtClassLoader
var1 = Launcher.ExtClassLoader.getExtClassLoader();
} catch (IOException var10) {
throw new InternalError("Could not create extension class loader", var10);
}
try {
// 创建一个 AppClassLoader类加载器 将 ExtClassLoader作为它的parent
// 并且将this.loader 的值赋为 AppClassLoader,这个也就是initSystemClassLoader 获得的值
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
} catch (IOException var9) {
throw new InternalError("Could not create application class loader", var9);
}
// 设置当前线程的类加载器为AppClassLoader
Thread.currentThread().setContextClassLoader(this.loader);
String var2 = System.getProperty("java.security.manager");
if (var2 != null) {
SecurityManager var3 = null;
if (!"".equals(var2) && !"default".equals(var2)) {
try {
var3 = (SecurityManager)this.loader.loadClass(var2).newInstance();
} catch (IllegalAccessException var5) {
} catch (InstantiationException var6) {
} catch (ClassNotFoundException var7) {
} catch (ClassCastException var8) {
}
} else {
var3 = new SecurityManager();
}
if (var3 == null) {
throw new InternalError("Could not create SecurityManager: " + var2);
}
System.setSecurityManager(var3);
}
}
}
我们尝试给
initSystemClassLoader
函数打断点,发现它一直是有值的用于进不去,什么使用初始化过了呢?
- 下载openjdk的源码,发现一个叫
SystemDictionary.cpp
的文件有一个这样的方法,此方法会在Threads::create_vm
中调用
void SystemDictionary::compute_java_system_loader(TRAPS) {
KlassHandle system_klass(THREAD, WK_KLASS(ClassLoader_klass));
JavaValue result(T_OBJECT);
// 调用java的getSystemClassLoader()函数
JavaCalls::call_static(&result,
KlassHandle(THREAD, WK_KLASS(ClassLoader_klass)),
vmSymbols::getSystemClassLoader_name(),
vmSymbols::void_classloader_signature(),
CHECK);
_java_system_loader = (oop)result.get_jobject();
CDS_ONLY(SystemDictionaryShared::initialize(CHECK);)
}
- 还有就是为什么第一次的断点进不去,那是因为第一次调用属于还没到java层面,debug包都没加载,怎么打断点
- 此部分自己也不是很熟悉,所以没有写很多