最新域名网站查询,奎文营销型网站建设,设计软件ai,不良网站进入窗口参考如下三篇并整理。 1.Java类加载机制详解 2.深入理解Java#xff1a;类加载机制及反射 3.jvm系列(一):java类的加载机制 类的生命周期是从被加载到虚拟机内存中开始#xff0c;到卸载出内存结束。过程共有七个阶段。 1.加载---2.验证---3.准备---3.解析---5.初始化---6.使…参考如下三篇并整理。 1.Java类加载机制详解 2.深入理解Java类加载机制及反射 3.jvm系列(一):java类的加载机制 类的生命周期是从被加载到虚拟机内存中开始到卸载出内存结束。过程共有七个阶段。 1.加载---2.验证---3.准备---3.解析---5.初始化---6.使用---7.卸载 |________连接________| |______________类的加载过程_____________| |______________________类的生命周期_______________________| 其中类加载的过程包括了加载、验证、准备、解析、初始化五个阶段。 在这五个阶段中加载、验证、准备和初始化这四个阶段发生的顺序是确定的而解析阶段则不一定它在某些情况下可以在初始化阶段之后开始这是为了支持Java语言的运行时绑定也成为动态绑定或晚期绑定。 另外注意这里的几个阶段是按顺序开始而不是按顺序进行或完成因为这些阶段通常都是互相交叉地混合进行的通常在一个阶段执行的过程中调用或激活另一个阶段。 【1.加载装载】 在装载阶段虚拟机需要完成以下3件事情 (1) 通过一个类的全限定名来获取定义此类的二进制字节流。 (2) 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。 (3) 在Java堆中生成一个代表这个类的java.lang.Class对象作为方法区这些数据的访问入口。 虚拟机规范中并没有准确说明二进制字节流应该从哪里获取以及怎样获取,这里可以通过定义自己的类加载器去控制字节流的获取方式。 这里第1条中的二进制字节流并不只是单纯地从Class文件中获取比如它还可以从Jar包中获取、从网络中获取最典型的应用便Applet、由其他文件生成JSP应用等。 相对于类加载的其他阶段而言加载阶段准确地说是加载阶段获取类的二进制字节流的动作是可控性最强的阶段因为开发人员既以使用系统提供的类加载器来完成加载也可以自定义自己的类加载器来完成加载。 【2.验证校验、检查】 虚拟机如果不检查输入的字节流对其完全信任的话很可能会因为载入了有害的字节流而导致系统奔溃。 1.文件格式验证验证字节流是否符合Class文件格式的规范例如是否以0xCAFEBABE开头、主次版本号是否在当前虚拟机的处理范围之内、常量池中的常量是否有不被支持的类型。 2.元数据验证对字节码描述的信息进行语义分析注意对比javac编译阶段的语义分析以保证其描述的信息符合Java语言规范的要求例如这个类是否有父类除了java.lang.Object之外。 3.字节码验证通过数据流和控制流分析确定程序语义是合法的、符合逻辑的。 4.符号引用验证确保解析动作能正确执行。 验证阶段是非常重要的但不是必须的它对程序运行期没有影响如果所引用的类经过反复验证 那么可以考虑采用-Xverifynone参数来关闭大部分的类验证措施以缩短虚拟机类加载的时间。 【3.准备】————为类的静态变量分配内存并将其初始化为默认值 这个阶段正式为类变量被static修饰的变量分配内存并设置类变量初始值这个内存分配是发生在方法区中。 1、注意这里并没有对实例变量进行内存分配实例变量将会在对象实例化时随着对象一起分配在JAVA堆中。 2、这里设置的初始值通常是指数据类型的‘“零”值。 public static int value 123; value在准备阶段过后的初始值为0而不是123,而把value赋值的putstatic指令将在初始化阶段才会被执行。 注意 1对基本数据类型来说对于类变量static和全局变量如果不显式地对其赋值而直接使用则系统会为其赋予默认的零值。 2对基本数据类型来说对于局部变量来说在使用前必须显式地为其赋值否则编译时不通过。 3对于同时被static和final修饰的常量必须在声明的时候就为其显式地赋值否则编译时不通过 4只被final修饰的常量则既可以在声明时显式地赋值也可以在类初始化时显式地为其赋值总之在使用前必须为其显式地赋值系统不会为其赋予默认零值。 5对于引用数据类型reference来说如数组引用、对象引用等如果没有对其进行显式地赋值而直接使用系统都会为其赋予默认的零值即null。 6如果在数组初始化时没有对数组中的各元素赋值那么其中的元素将根据对应的数据类型而被赋予默认的零值。 3、static final常量在准备阶段变量value就会被初始化为ConstValue属性所指定的值将其结果放入了调用它的类的常量池中。 public static final int value 3 编译时Javac将会为value生成ConstantValue属性在准备阶段虚拟机就会根据ConstantValue的设置将value赋值为3。 下表列出了Java中所有基本数据类型以及reference类型的默认零值 【4.解析】————把类中的符号引用转换为直接引用 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。 符号引用就是一组符号来描述目标可以是任何字面量。 直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。 1、类或接口的解析判断所要转化成的直接引用是对数组类型还是普通的对象类型的引用从而进行不同的解析。 2、字段解析对字段进行解析时会先在本类中查找是否包含有简单名称和字段描述符都与目标相匹配的字段如果有则查找结束 如果没有则会按照继承关系从上往下递归搜索该类所实现的各个接口和它们的父接口还没有则按照继承关系从上往下递归搜索其父类直至查找结束查找流程如下图所示 3、类方法解析对类方法的解析与对字段解析的搜索步骤差不多只是多了判断该方法所处的是类还是接口的步骤而且对类方法的匹配搜索是先搜索父类再搜索接口。 4、接口方法解析与类方法解析步骤类似知识接口不会有父类因此只递归向上搜索父接口就行了。 【5.初始化】 详细见此 类初始化时机只有当对类的主动使用的时候才会导致类的初始化类的主动使用包括以下四大种六小种 【1】在如下三个场景能生成四个字节码指令的场景如果类还未初始化则初始化。 4个指令【new、getstatic、putstatic、invokestatic】 A.new new Test(); B.读取或设置类的静态变量 int bTest.a;Test.ab; C.调用静态函数 Test.doSomething(); 【2】反射调用。 Class.forName(“com.mengdd.Test”); 【3】子类初始化要先初始化父类所有父类。 【4】虚拟机启动时要初始化主类。直接使用java.exe命令来运行某个主类。 只有上述四种情况会触发初始化也称为对一个类进行主动引用。 除此以外有其他方式都不会触发初始化称为被动引用。 注意 1子类引用父类的静态变量不会导致子类初始化。 2通过数组定义引用类不会触发此类的初始化 3引用常量时不会触发该类的初始化 举例 1子类引用父类的静态变量不会导致子类初始化。 public class SupClass
{public static int a 123;static{System.out.println(supclass init);}
}public class SubClass extends SupClass
{static{System.out.println(subclass init);}
}public class Test
{public static void main(String[] args){System.out.println(SubClass.a);}
} 执行结果 supclass init
123 2通过数组定义引用类不会触发此类的初始化 public class SupClass
{public static int a 123;static{System.out.println(supclass init);}
}public class Test
{public static void main(String[] args){SupClass[] spc new SupClass[10];}
} 执行结果 3引用常量时不会触发该类的初始化 public class ConstClass
{public static final String A MIGU;static{System.out.println(ConstCLass init);}
}public class TestMain
{public static void main(String[] args){System.out.println(ConstClass.A);}
} 执行结果 MIGU 用final修饰某个类变量时它的值在编译时就已经确定好放入常量池了所以在访问该类变量时等于直接从常量池中获取并没有初始化该类。 初始化的步骤 1、如果该类还没有加载和连接则程序先加载该类并连接。 2、如果该类的直接父类没有加载则先初始化其直接父类。 3、如果类中有初始化语句则系统依次执行这些初始化语句。 在第二个步骤中如果直接父类又有直接父类则系统会再次重复这三个步骤来初始化这个父类 依次类推JVM最先初始化的总是java.lang.Object类。 当程序主动使用任何一个类时系统会保证该类以及所有的父类都会被初始化。 【6.使用】 【7.卸载】 在如下几种情况下Java虚拟机将结束生命周期 1.执行了System.exit()方法 2.程序正常执行结束 3.程序在执行过程中遇到了异常或错误而异常终止 4.由于操作系统出现错误而导致Java虚拟机进程终止 转载于:https://www.cnblogs.com/CESC4/p/8037858.html