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将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

SpringMVC 通过ajax 前后端数据交互的实现方法

《SpringMVC通过ajax前后端数据交互的实现方法》:本文主要介绍SpringMVC通过ajax前后端数据交互的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价... 在前端的开发过程中,经常在html页面通过AJAX进行前后端数据的交互,SpringMVC的controll

Java中的工具类命名方法

《Java中的工具类命名方法》:本文主要介绍Java中的工具类究竟如何命名,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java中的工具类究竟如何命名?先来几个例子几种命名方式的比较到底如何命名 ?总结Java中的工具类究竟如何命名?先来几个例子JD

Java Stream流使用案例深入详解

《JavaStream流使用案例深入详解》:本文主要介绍JavaStream流使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录前言1. Lambda1.1 语法1.2 没参数只有一条语句或者多条语句1.3 一个参数只有一条语句或者多