类加载子系统
内存结构概述
图中是虚拟机的内存模型,每一个环节所作的任务,在后续都会带给大家作理解的。
类加载器与类的加载过程
类加载子系统的作用
负责从文件系统或者网络中加载带有魔数标识的java字节码文件。
ClassLoader只负责字节码的加载,至于它是否会执行成功,那么是需要执行引擎去做决定。
类加载之后的信息,存放在方法区,包括字符串常量也放在方法区,后来改名为永久代,再后来改名为元空间。
类加载器ClassLoader的角色
1、class字节码文件是存放在本地硬盘上的,那么它如果在硬盘上就只是一个class字节码文件,它的信息包含了什么?那么就需要加载到jvm上编译成机器能够识别的机器码指令来解释运行。
2、class字节码文件加载到虚拟机中被称为DAN元数据模板,放在方法区。
3.从class file->JVM->到DAN模板 就需要ClassLoader来承载一个传递的角色。
类的加载过程
加载
1、通过一个类的全限定名来获取一个二进制流文件。
2、将这个二进制文件,转化为方法区的运行时数据结构
3、在内存中生成一个一个代表这个类的Class对象,作为方法区的各个数据的访问入口。
链接
分为验证、准备、解析三个环节。 准备环节最为重要。
准备阶段做的工作:
1 为类变量分配内存,并初始化为默认值。 在初始化阶段 显示赋值。
2 final修饰的变量在类刚加载的时候就会分配内存,准备阶段会进行显示初始化。
3 不会为实例变量分配初始化,类变量分配在方法区,而实例变量分配在堆中。
初始化
初始化阶段就是执行类的方法,即类构造器方法
此方法不需要定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码快中的语句合并而来。
此构造器方法的执行指令,按照class文件中的顺序来执行。
当一类有父类的时候,首先执行的是父类中的构造器方法。
虚拟机保证了一个类的构造器方法在多线程情况下被加锁。因为要确保一个类能被安全的加载并初始化各个值。
类加载器的分类
引导类加载器(BootStrap ClassLoader)
- 引导类加载器是由C++编写的,我们不能获取,它没有父类加载器。
- 嵌套在JVM内部
- 用来加载Java的核心库(Java_Home/jre/lib/rt.jar等),用于提供JVM自身需要的类。
- 用于加载扩展类加载器和系统类加载器,并指定为它们的父类加载器
- 出去安全考虑,只加载包名为java,javax,sun等开头得类。
扩展类加载器(Extension ClassLoader)
- java语言实现
- 派生于ClassLoder类
- 父类加载器是BootStrapClassLoader
- 从java.ext.dirs系统属性所指定的目录加载类库,或从JDK的安装目录的jre/lib/ext子目录下加载类库。如果我们自己创建的jar放在此目录下,也会被扩展类加载器加载。
系统类加载器(System ClassLoader)
- java语言编写
- 派生于ClssLoader类
- 父类加载器是Extension ClassLoader加载器
- 负责加载环境变量或系统属性java.class.path指定下的类库
- 该类是程序中默认的加载器,一般java的类都是它加载。
- 通过ClassLoader.getSystemClassLoader()方法可以获取该类的加载器
获取ClassLoade的方式
//通过类获得类的加载器
方式一:clazz.getClassLoader()
//从当前线程中获取上下文的加载器
方式二:Thread.currentThread().getContextClassLoader();
//通过ClassLoader来获得类的加载器
方式三:ClassLoader.getSystemClassLoader().getparent();
方式四:DriverManager.getCallerClassLoader() //很少用
双亲委派机制
Java虚拟机对class文件采用的是按需加载,当我需要class文件的时候,才将它的class文件加载到内存生成class对象。加载class文件的时候,是通过双亲委派机制加载。
一个类收到加载请求的时候不会自己去加载,而是从系统类加载器,扩展类加载器,引导类加载器依次向上委托。如果父类加载器能加载,则父类加载,不能再返回下一级加载。
优点:
可以避免类的重复加载;
防止核心API被更改
沙箱安全机制
沙箱安全机制就是对于java中的一些类比如
String 如果我在java包下创建一个lang包再创建一个String类
那么我们再使用String类的时候就不能使用,是因为沙箱安全机制。
如下:
这就是沙箱安全机制。
码字不易。。。。一键三连吧。