一、Java类加载机制
jvm把class文件加载到内存,并对数据进行校验、解析和初始化,最终形成jvm可以直接使用的java类型的过程。
- 加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在推中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口。
- 链接:将java类的二进制代码合并到jvm的运行状态之中的过程,链接过程又分为3个过程:
2.1验证:确保加载的类信息符合jvm规范,没有安全方法的问题。
2.2准备:正式为类变量(static变量)分配内存并设置类变量初始值额阶段,哲学和内存都贱狗仔方法区中进行分配.
2.3解析:虚拟机常量池内的符号应用替换为直接引用的过程。(比如String=”aaa”,转化为s的地址指向”aaa”的地址) - 初始化:初始化阶段是执行类构造器方法的过程。类构造器方法是有编译器自动收集类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的。
当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先初始化其父类的初始化
虚拟机会保证一个类的构造器方法在多线程环境中被正确加锁和同步
当访问一个java类的静态域时,只有真正声明这个静态变量的类才会被初始化。
Java的生命周期
二、ClassLoader类的加载器
ClassLoader类加载器的作用就是将 .class 文件加载到JVM虚拟机中去
代码如下:public class ClassLoaderDemo {
public static void main(String[] args) throws ClassNotFoundException {
//获取类加载器
ClassLoader classLoader=ClassLoaderDemo.class.getClassLoader();
System.out.println(classLoader);
//常用三种方式加载类
//使用ClassLoader.loadClas()来加载类,不会执行初始化块
System.out.println("—ClassLoader.loadClass()—");
classLoader.loadClass(“com.gx.reflect.Test1”);
//使用Class.forName(className)来加载类,默认会执行初始化块
System.out.println("—Class.forName(className)—");
Class.forName(“com.gx.reflect.Test2”);
//使用Class.forName(className,initialize,ClassLoader)来加载类,并指定ClassLoader,初始化时不执行静态代码块
//参数:类名,是否初始化,类加载器
System.out.println("—Class.forName(className,initialize,ClassLoader)—");
Class.forName(“com.gx.reflect.Test3”,true,classLoader);
}
}
class Test1{ static {System.out.println(“Test1 静态初始化块”);}}
class Test2{ static {System.out.println(“Test2 静态初始化块”);}}
class Test3{ static {System.out.println(“Test3 静态初始化块”);}}
三、Java反射机制
在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够 调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的 功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何 东西都可以。