JavaJAVA

JVM(二)内存与垃圾回收|类加载子系统

2020-06-07  本文已影响0人  TiaNa_na

在JVM概述中我们已经了解了JVM体系结构,下文将深入介绍JVM体系结构之一的类加载子系统。

目录
 1 类加载子系统作用
 2 类加载器 ClassLoader角色
 3 类加载过程
 4 类加载器分类
  4.1 ClassLoader的常用方法及获取方法
  4.2虚拟机自带的加载器
  4.3用户自定义类加载器
 5 双亲委派机制
  5.1 工作原理
  5.2 沙箱安全机制
  5.3 双亲委派机制的优势
 6 类的主动使用和被动使用

1 类加载子系统作用
类加载子系统
2 类加载器 ClassLoader角色
类加载器 ClassLoader角色
3 类加载过程
类加载过程
①加载

②验证

③准备

④解析

⑤初始化

4 类加载器分类
4.1 ClassLoader的常用方法及获取方法

在了解JVM分类之前,先来了解ClassLoader的常用方法及获取方法

方法名称 描述
getParent() 返回该类加载器的超类加载器
loadClass(String name) 加载名称为name的类,返回结果为java.lang.Class类的实例
findClass(String name) 查找名称为name的类,返回结果为java.lang.Class类的实例
findLoadedClass(String name) 查找名称为name的已经被加载过的类,返回结果为java.lang.Class类的实例
defineClass(String name,byte[] b,int off,int len) 把字节数组b中的内容转换为一个Java类 ,返回结果为java.lang.Class类的实例
resolveClass(Class<?> c) 连接指定的一个java类

①获取当前类的ClassLoader

ClassLoader classLoader = Class.forName("java.lang.String").getClassLoader();
System.out.println(classLoader); //null

②获取当前线程上下文的ClassLoader

ClassLoader classLoader1 = Thread.currentThread().getContextClassLoader();
System.out.println(classLoader1);

③获取系统的ClassLoader

ClassLoader classLoader2 = ClassLoader.getSystemClassLoader().getParent();
System.out.println(classLoader2);

④获取调用者的ClassLoader

4.2虚拟机自带的加载器

①启动类加载器(引导类加载器,BootStrap ClassLoader)

②拓展类加载器(Extension ClassLoader)

③应用程序类加载器(系统类加载器,AppClassLoader)

上文中提及的父子加载器并非简单的继承关系而是双亲委派模式,下文第五节将详细说明此内容。

4.3用户自定义类加载器

①为什么要自定义类加载器
隔离加载类
修改类加载的方式
拓展加载源
防止源码泄漏
②自定义类加载器的实现
参考https://segmentfault.com/a/1190000012925715

5 双亲委派机制

Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成的class对象。而且加载某个类的class文件时,java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式。

5.1 工作原理

思考:能不能自己写个java.lang.String类?
如下,我们自己定义一个java.lang.String类。由于双亲委派机制,启动加载器会加载java核心类库的String类(BootStrap启动类加载器加载包名以java、javax、sun等开头的类),而自己写的String类根本没有机会得到加载。

package java.lang;
public class String {
    //
    static{
        System.out.println("我是自定义的String类的静态代码块");
    }
    public static void main(String[] args) {
        System.out.println("hello,String");
    }
}

什么地方违反了双亲委派模型

5.2 沙箱安全机制

自定义String类,在加载自定义String类的时会率先使用引导类加载器加载,而引导类加载器在加载过程中会先加载jdk自带的文件(rt.jar包中的java\lang\String.class),报错信息说没有main方法就是因为加载的是rt.jar包中的String类。这样可以保证对java核心源代码的保护,这就是沙箱安全机制

在jvm中表示两个class对象是否为同一个类存在的两个必要条件:

  • 类的完整类名必须一致,包括包名
  • 加载这个类的ClassLoader(指ClassLoader实例对象)必须相同
    换句话说,在jvm中,即使这两个类对象(class对象)来源同一个Class文件,被同一个虚拟机所加载,但只要加载它们的ClassLoader实例对象不同,那么这两个类对象也是不相等的.
5.3 双亲委派机制的优势
6 类的主动使用和被动使用

①JVM必须知道一个类型是有启动类加载器加载的还是由用户类加载器加载的。如果一个类型由用户类加载器加载的,那么jvm会将这个类加载器的一个引用作为类型信息的会议部分保存在方法区中。当解析一个类型到另一个类型的引用的时候,JVM需要保证两个类型的加载器是相同的。

②java程序对类的使用方式分为:主动使用和被动使用

主动使用,分为七种情况:

除了以上七种情况,其他使用java类的方式都被看作是对类的被动使用,都不会导致类的初始化。

上一篇下一篇

猜你喜欢

热点阅读