java虚拟机:ClassLoader分析

2024-08-24 05:32

本文主要是介绍java虚拟机:ClassLoader分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

序言

最近看了看ClassLoader,网上的博客挺多的,大部分都是你抄我的,我抄你的。在他们的基础上,自己打算写一篇,自己对ClassLoader的分析,也就是对现有blog的总结吧。

ClassLoader初始化源码。

在openjdk中可以看到下面的代码。

public Launcher() {// Create the extension class loaderClassLoader extcl;try {extcl = ExtClassLoader.getExtClassLoader();} catch (IOException e) {throw new InternalError("Could not create extension class loader");}// Now create the class loader to use to launch the applicationtry {loader = AppClassLoader.getAppClassLoader(extcl);} catch (IOException e) {throw new InternalError("Could not create application class loader");}// Also set the context class loader for the primordial thread.Thread.currentThread().setContextClassLoader(loader);// Finally, install a security manager if requestedString s = System.getProperty("java.security.manager");if (s != null) {SecurityManager sm = null;if ("".equals(s) || "default".equals(s)) {sm = new java.lang.SecurityManager();} else {try {sm = (SecurityManager)loader.loadClass(s).newInstance();} catch (IllegalAccessException e) {} catch (InstantiationException e) {} catch (ClassNotFoundException e) {} catch (ClassCastException e) {}}if (sm != null) {System.setSecurityManager(sm);} else {throw new InternalError("Could not create SecurityManager: " + s);}}
}

可以看到在Launcher构造函数的执行过程如下:

  1. 通过ExtClassLoader.getExtClassLoader()创建了ExtClassLoader;

  2. 通过AppClassLoader.getAppClassLoader(ExtClassLoader)创建了AppClassLoader,并将ExtClassLoader设为AppClassLoader的parent
    ClassLoader;

  3. 通过Thread.currentThread().setContextClassLoader(loader)把AppClassLoader设为线程的上下文
    ClassLoader;

JDK默认ClassLoader:

在jdk中默认了3种的ClassLoader:BootStrapClassLoader、ExtensionClassLoader和AppClassLoader。

  1. BootStrapClassLoader:它是最顶层的类加载器,是由C++编写而成,
    已经内嵌到JVM中了。在JVM启动时会初始化该ClassLoader,它主要用来读取Java的
    核心类库JRE/lib/rt.jar中所有的class文件,这个jar文件中包含了java规范定义的所有接口及实现。
  2. ExtensionClassLoader:它是用来读取Java的一些扩展类库,如读取JRE/lib/ext/*.jar中的包等(这里要注意,有些版本的是没有ext这个目录的)。
  3. AppClassLoaderBootstrp
    loader加载完ExtClassLoader后,就会加载AppClassLoader,并且将AppClassLoader的父加载器指定为
    ExtClassLoader。AppClassLoader也是用Java写成的,它的实现类是
    sun.misc.Launcher$AppClassLoader,另外我们知道ClassLoader中有个getSystemClassLoader方法,此方法返回的正是AppclassLoader.AppClassLoader主要负责加载classpath所指定的位置的类或者是jar文档,它也是Java程序默认的类加载器。

ClassLoader源码阅读

##成员变量
private final ClassLoader parent;
父类的加载器,所有的新的变量都必须在它之后,英文: The parent class loader for delegation.Note: VM hardcoded the offset of this field, thus all new fields must be added after it.

private final ConcurrentHashMap parallelLockMap;
当前ClassLoader在并发情况下,一个锁的的对象。 Maps class name to the corresponding lock object when the current class loader is parallel capable. Note: VM also uses this field to decide if the current class loader is parallel capable and the appropriate lock object for class loading.

private final Map package2cert;

每个包的证书,是个HashTable

private static final Certificate[] nocerts = new Certificate[0];

Shared among all packages with unsigned classes

private final Vector> classes = new Vector<>();
这个class loader加载的所有类,这些类是从开始被GC到gc结束 The classes loaded by this class loader. The only purpose of this table is to keep the classes from being GC’ed until the loader is GC’ed.

private final ProtectionDomain defaultDomain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), null, this, null);

貌似是读写的策略,The “default” domain. Set as the default ProtectionDomain on newly created classes.

private final Set domains;

The initiating protection domains for all classes loaded by this loader

构建函数

私有的构造函数

   private ClassLoader(Void unused, ClassLoader parent) {this.parent = parent;if (ParallelLoaders.isRegistered(this.getClass())) {parallelLockMap = new ConcurrentHashMap<>();package2certs = new ConcurrentHashMap<>();domains =Collections.synchronizedSet(new HashSet<ProtectionDomain>());assertionLock = new Object();} else {// no finer-grained lock; lock on the classloader instanceparallelLockMap = null;package2certs = new Hashtable<>();domains = new HashSet<>();assertionLock = this;}}

也就是分为当前的ClassLoader是否被加载2种情况:ParallelLoaders.isRegistered(this.getClass())来判断是否可以并行

保护性的构造函数

 protected ClassLoader(ClassLoader parent) {this(checkCreateClassLoader(), parent);}protected ClassLoader() {this(checkCreateClassLoader(), getSystemClassLoader());}

checkCreateClassLoader():是校验下创建ClassLoader的权限
parent:是创建ClassLoader的父节点
getSystemClassLoader():是获取系统的ClassLoader,作为当前节点的父节点
3. loadClass

resolve:在虚拟机中找到一个类二进制,再根据resolve参数判断Classloader用来链接一个类

  protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}

先进行getClassLoadingLock(以后会详细分析),然后查找已加载的类,在从父类ClassLoader查找,最后查找Bootstrap的ClassLoader

resolveClass:链接指定的类。这个方法给Classloader用来链接一个类,如果这个类已经被链接过了,那么这个方法只做一个简单的返回。否则,这个类将被按照 Java™规范中的Execution描述进行链接

##参照:
http://www.hollischuang.com/archives/199

这篇关于java虚拟机:ClassLoader分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1101579

相关文章

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

Java中StopWatch的使用示例详解

《Java中StopWatch的使用示例详解》stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,这篇文章主要介绍... 目录stopWatch 是org.springframework.util 包下的一个工具类,使用它

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义