/**
* 【JVM-类加载子系统-作用】
* 负责 从文件系统 或 网络中加载class文件;
* ClassLoader 只负责 class文件的加载,至于 是否可以运行,由 Execution Engine决定;
* 加载的 类元数据信息 存放于 方法区的内存空间;
* (除了类元数据信息外,方法区还会存放运行时常量池信息:字符串字面量、数字常量[这部分常量信息 是class文件中常量池部分的内存映射])
*/
/**
* 【JVM-类加载子系统-类加载】
* 加载loading:
* a,通过 类的全限定名 获取定义此类的 二进制字节流;
* 加载class文件方式:
* 本地文件系统;
* 网络;
* jar,war,zip包...
* 运行时计算生成:动态代理...
* 其他文件生成:JSP
* ...
*
* b,将 定义类的 静态存储结构 转化为 方法区的运行时数据结构;
* c,在 内存中 生成一个代表 该类的java.lang.Class对象,作为 方法区 这个类的各种元数据信息 的访问入口;
*
*
* 链接linking:
* a,验证verify:
* 文件格式校验
* 开头是否以0xCAFEBABE
* ...
* 元数据验证
* 进行语义分析:是否有父类?是否继承final类?...
* 字节码验证
* 符号引用验证
*
* b,准备prepare:
* 为 static变量 在方法区 分配内存,并 赋初始值;
* 对于 final static 变量,编译时就已经设置初始值,准备阶段 显式 初始化;
*
* c,解析resolve:
* 将 常量池 中的 符号引用 转化为 直接引用;
*
*
* 初始化initialization:
* 执行 () 的过程;
*
* ():
* 1、来源:
* javac编译器 自动收集 类中 所有 static 变量的 赋值内容 (包括 static{} 的内容);
*
* 2、指令执行顺序 :
* 声明顺序 ;
* eg:
* static {
* a = 2;
* System.out.println(a); // 报错:非法前向引用
* }
*
* private static int a = 1;
*
* 先使用-后声明:
* static变量a 在linking-prepare时 已经赋初始值0,所以 初始化阶段执行() 是可以的;
* 【仅允许赋值,不允许调用】;
*
* ():
* iconst_2
* putstatic
* iconst_1
* putstatic
* return
*
* 3、如果 类 中没有 static 变量 、没有 static 代码块, javac编译后不会生成 ();
* :
* 类的构造器;
* 任何一个类声明后,内部至少存在一个类的构造器;
*
* 4、执行 子类的 () 前 ,必须 保证 父类的()执行完毕;
*
* 5、JVM 必须 保证 一个类的() 在多线程 下 被 同步加锁;
*
*/
/**
* 【JVM-类加载子系统-类加载器】
* JVM支持2种类型的类加载器:
* 引导类加载器Bootstrap ClassLoader:
* 自定义类加载器:
* JVM规范中,将所有派生于ClassLoader的类加载器 称为 自定义类加载器;
*
* sun.misc.Launcher 是一个JVM的入口应用;
* public class Launcher {
* static class AppClassLoader extends URLClassLoader {}
*
* static class ExtClassLoader extends URLClassLoader {}
* }
*
* java.net.URLClassLoader
* public class URLClassLoader extends SecureClassLoader implements Closeable {}
*
* java.security.SecureClassLoader
* public class SecureClassLoader extends ClassLoader {}
*
* java.lang.ClassLoader
* public abstract class ClassLoader {}
*
*
* 引导类加载器、拓展类加载器、系统类加载器、用户自定义类加载器 的关系:
* 包含关系 (不是上下层、不是继承关系)
*
* 类加载器之间的这种层级关系,称为 类加载器的双亲委派模型;
* 双亲委派模型 要求 除了顶层的启动类加载器外,其余的类加载器应有自己的父类加载器;
* 父子关系不会以继承的关系实现,而是使用组合关系来复用父类加载器;
*
* a,引导类加载器Bootstrap ClassLoader
* 使用 C/C++实现,嵌套在JVM内部;
* 不继承自java.lang.ClassLoader,无父类加载器;
* 加载 拓展类加载器 、系统类加载器;
* 出于安全考虑,Bootstrap ClassLoader只加载java、javax、sun等开头的类;
* 作用:
* 加载 Java的核心类库
* (java_home/jre/lib/rt.jar、resources.jar或sun.boot.class.path路径下的内容)
* 用于JVM自身需要的类;
*
* URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs();
* for(URL url : urLs){
* System.out.println(url.toExternalForm());
* }
*
* //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/resources.jar
* //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/rt.jar
* //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/sunrsasign.jar
* //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jsse.jar
* //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jce.jar
* //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/charsets.jar
* //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/jfr.jar
* //file:/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/classes
*
* b,拓展类加载器ExtClassLoader
* 使用Java实现,sun.misc.Launcher.ExtClassLoader;
* 继承自ClassLoader;
* 作用:
* 加载 jre/lib/ext 目录下的类库;
*
* String property = System.getProperty("java.ext.dirs");
* for(String path : property.split(":")){
* System.out.println(path);
* }
*
* // /Users/an/Library/Java/Extensions
* // /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/ext
* // /Library/Java/Extensions
* // /Network/Library/Java/Extensions
* // /System/Library/Java/Extensions
* // /usr/lib/java
*
*
* c,系统类加载器
* 使用Java实现,sun.misc.Launcher.AppClassLoader;
* 继承自ClassLoader;
* 作用:
* 加载 classpath或java.class.path 下 用户 自定义类;
*
* d,用户自定义类加载器
* 为什么要自定义?
* a,隔离 加载类;
* b,修改 类的加载方式;
* c,拓展 加载源;
* d,防止 源码泄漏;
*
* 自定义步骤:
* 第一种:
* a,继承 java.lang.ClassLoader
* b,重写 findClass()
*
* 第二种:
* 如果没有过多的逻辑,可以直接 继承 java.net.URLClassLoader;
*
* java.lang.ClassLoader
* public abstract class ClassLoader {
*
* // 根据 class全限定名称 加载Class
* public Class<?> loadClass(String name) throws ClassNotFoundException {}
* }
*
*/
/**
* 【JVM-类加载子系统-双亲委派机制】
* JVM 对 class文件 采用的是 按需加载(使用该类时,再进行加载);
* 加载 某个class文件时,采用 双亲委派机制 (把 加载请求 交由 上级加载器 加载);
* 如果 上级 类加载器 不能完成 类的加载,才由 本级类加载器 去加载;
*
* 优势:
* 避免类的重复加载;
* 保护程序安全,防止 核心 API 被篡改;
* eg:
* 自定义 java.lang.String类...
*/
/**
* 【JVM-类加载子系统-其他】
* 在同一个JVM中,表示2个class对象是否一致的必要条件: 类全限定名 + ClassLoader
* a, 类的全限定名称相同
* b, 加载该类的ClassLoader相同
*
* 类的主动使用和被动使用
* 主动使用:
* 创建类的实例;
* 访问某个类或接口的static变量 或 对static变量赋值;
* 调用类的static方法
* 反射(Class.forName(""))
* 初始化一个类的子类
* JVM启动时 被标明为 启动类的类
* 动态语言支持:
*
* 被动使用:
* 除主动使用外,都是被动使用;
*
* 主动使用与被动使用的区别:
* 被动使用 不会导致 类的初始化;
*
*/