JVM内部架构包含类加载器、内存区域、执行引擎等。日常开发中,我们编写的java文件被编译成class文件后,jvm会进行加载并运行使用类。本次仅对JVM加载部分进行分析,了解并掌握加载机制。
类加载是一种过程,是将class文件加载到jvm内存的过程。当代码逻辑中需要引用类时,通过类加载器加载引用类对象并存放堆中,以供代码调用。
注:类加载过程包含 加载、链接(验证、准备、解析)、初始化
加载:将类的class字节码文件读到内存,将其存放到运行时数据区的方法区,然后在堆区生成class对象,封装类在方法区内的数据结构。(方法区-》数据结构,堆区-》class对象)
过程:java文件-》通过java c编译成字节码.class文件-》引导类加载器(装载核心类库)-》扩展类加载器(将指定目录jar包装载至工作库)-》系统类加载器(将指定目录的类和jar包装载至工作库,常用)-》自定义类加载器(实现加载指定类或自定义加密等操作)
缓存:类加载到jvm后,会缓存一段时间(不管是否被引用),待jvm执行垃圾回收时才会回收未使用的缓存类,释放空间。
类加载器:
sun.misc.Launcher$ExtClassLoader
实现。加载java平台扩展的jar包,负责加载(java.ext.dirs目录或$JAVA_HOME
中jre/lib/ext
目录,如javax.开头的类)的class文件。sun.misc.Launcher$AppClassLoader
实现。负责加载用户类路径(classpath)的class文件,java程序一般默认使用应用程序类加载器。类加载机制
加载实现方式
/*
* 类加载方式
* 1、类加载器,此方式加载的class对象还没有完成链接阶段
* 2、java.lang.Class,此方式加载的class对象是完成初始化的
* */
ClassLoader classLoader = ClassSegregationTest.class.getClassLoader();
classLoader.loadClass("com.lgy.example.class_segregation.SegregationTestA");
// 默认初始化class对象
Class.forName("com.lgy.example.class_segregation.SegregationTestA");
// 默认不初始化,并且指定类加载器进行加载
Class.forName("com.lgy.example.class_segregation.SegregationTestA", false, classLoader);
链接是将java二进制代码合并至jvm运行的过程。
链接过程可分为 验证、准备、解析 三个阶段。
验证
准备
解析
执行每个类的构造方法init()的过程,init()方法是java编译器自动收集、合并所有类变量的赋值动作和静态代码块语句,完成初始化。
初始化步骤
初始化条件(只有对类主动使用时才会初始化类)
演示代码如下:
/**
* 定义父类与子类
*/
class Parent {
public static int a = 10;
static {
System.out.println(" 父类初始化 ");
}
}
class Children extends Parent{
public static int a = 100;
static {
System.out.println(" 子类初始化 ");
}
}
public static void main(String[] args) throws Exception {
// 子类没有定义变量a ( public static int a = 100;)
System.out.println(Children.a); // 输出 -- 父类初始化 -- 10
// 主动调用时才会执行类的静态块
-----------------------------------------
// 子类定义变量a
System.out.println(Children.a); // 输出 -- 父类初始化 -- 子类初始化 -- 100
// 子类被初始化时,优先初始化父类,所以父类静态块执行;调用变量a属于子类定义,属于主动调用,所以子类静态块执行
}
以上就是关于自定义类加载器、加载过程的全部内容。
本文是针对于类隔离实现之自定义类加载器的扩展,对于应用中类加载阶段的进一步分析。
全部0条评论
快来发表一下你的评论吧 !