JVM总括四-类加载过程、双亲委派模型、对象实例化过程

目录:JVM总括:目录 一、 类加载过程 类加载过程就是将.class文件转化为Class对象,类实例化的过程,(User user = new User(); 这个过程是对象实例化的过程); 一个.class文件只有一个Class对象(字节码对象),可以有无数个对象(例如:new User();); 1、Load:   将编译后的.class文件以二进制流的方式加载到JVM内存中,并转化为特定的数据结构,用到的就是classLoad二类加载器。这个过程中校验cafe babe魔法数、常量池、文件长度、是否有父类等。 2、Link:   分为验证、准备、解析三步。   验证:更为详细的验证,比如:final是否规范(二次赋值不规范)、static是否合理(静态方法必须引用静态变量)、类型是否正确。   准备:静态变量分配内存并设定默认值(静态变量不赋值是有个默认值得),这个过程没有对象实例化。   解析:把类中的符号引用转化为直接引用,完成内存结构布局。(符号引用转化为直接引用:例如:test1() { test2(); },这里test1调用test2方法就是符号引用,但实际test2()通过一个指针指向test2方法的内存地址,这个指针负责调用,它就是直接引用)。 3、Init:   执行类构造器,执行静态代码块,为静态变量赋予正确的初始值,递归初始化父类,不执行构造函数。(先执行静态代码块,再执行静态变量)。 任何小写的class定义的类都有一个魔法属性:class, int j; Class integerClass = int.class; Class integerClass1 = Integer.class; 二、类加载的原则:双亲委派模型   类加载是怎么确定类文件的位置呢?   1、Bootstrap:最高级的类加载器,装置最核心的类,如:Object、System、String;   2、Extension ClassLoader:JDK9之前的类加载器,以后的为Platform ClassLoader,加载系统的扩展类;   3、Application ClassLoader:应用类加载器,主要加载用户自定义CLASSPATH路径下的类。 类加载器并非继承关系,只是以组合的方式服用父加载器功能,符合优先原则。 其中第二、第三层为java实现,用户可以自定义类加载器,第三层为C++实现,所有为null: 复制代码 ClassLoader classLoader = Son.class.getClassLoader(); ClassLoader parent = classLoader.getParent(); ClassLoader parent1 = parent.getParent(); System.out.println(classLoader); System.out.println(parent); System.out.println(parent1); ----------------------------------- sun.misc.Launcher$AppClassLoader@18b4aac2 sun.misc.Launcher$ExtClassLoader@5acf9800 null 复制代码 获取Bootstrap加载的类库: 复制代码 URLClassPath bootstrapClassPath = Launcher.getBootstrapClassPath(); URL[] urLs = bootstrapClassPath.getURLs(); for (URL url : urLs){ System.out.println(url.toExternalForm()); } --------------------------------------------------------- file:/D:/jdk-8u151-windows-x64/JDK/jre/lib/resources.jar file:/D:/jdk-8u151-windows-x64/JDK/jre/lib/rt.jar file:/D:/jdk-8u151-windows-x64/JDK/jre/lib/sunrsasign.jar file:/D:/jdk-8u151-windows-x64/JDK/jre/lib/jsse.jar file:/D:/jdk-8u151-windows-x64/JDK/jre/lib/jce.jar file:/D:/jdk-8u151-windows-x64/JDK/jre/lib/charsets.jar file:/D:/jdk-8u151-windows-x64/JDK/jre/lib/jfr.jar file:/D:/jdk-8u151-windows-x64/JDK/jre/classes 复制代码 Bootstrap加载的路径可以追加,在JVM增加启动参数,不过不建议修改: Xbootclasspath/D:/test/src 自定义类加载器的情况: 1、隔离加载类:框架中吧类加载到不同的环境中 2、修改类加载方式:除了Bootstrap,其他类并非一定要加入。 3、扩展加载源:比如加载数据库; 4、防止源码泄露:可以对类进行加密,那加载的时候需要自定义加载器对类进行解密加载。 自定义ClassLoder,继承ClassLoader,重写findClass(),调用defineClass(): UserClassLoader 调用,其中D:\\wp目录下为.class文件,里面有个Son.class 复制代码 //自定义类加载器的加载路径 UserClassLoader myClassLoader=new UserClassLoader("D:\\wp"); //包名+类名 Class sonClass=myClassLoader.loadClass("com.Son"); if(sonClass!=null){ Object obj=sonClass.newInstance(); System.out.println(sonClass.getClassLoader().toString()); } 复制代码 三、对象实例化 从字节码、执行步骤两个方面分析 1、字节码方面:   Object object = new Object();,通过javap -verbose -p查看对象创建的字节码指令:      (1)new:如果找不到Class对象就进行类加载,然后分配内存(本类路径上所有的属性都分配),其中对象的引用也是个变量也占内存(4个字节),这个指令执行完毕会把对象的压入虚拟机栈顶。   (2)dup:在栈顶复杂引用,如果有参数,把参数压入操作栈,两个引用,压入栈底的用来赋值或保存到局部变量表中,栈顶引用作为句柄调用相关方法。   (3)invokespecial:调用对象实例化方法,通过栈顶方法调用方法(也就是调用构造方法)。 2、执行步骤   (1)确认类元信息是否存在:接到new指令时,在metaspace检查类元信息是否存在,没有就在双亲委派模式下进行类加载,生成Class对象。   (2)分配对象内存:首先计算对象占用空间大小(成员变量是引用变量就分配4个字节大小的变量空间),在堆中划分内存空间给新对象(分配空间需要进行同步操作,如:cas)。   (3)设定默认值:成员变量设置不同形式的0值;   (4)设置对象头:设置对象的哈希码、锁信息、对象所属的类元信息,设置取决于JVM。   (5)执行init方法:初始化成员变量,执行代码块,调用类的构造方法,把堆对象首地址赋值给引用变量。 四、思考:ClassLoader.loadClasshe和Class.forName区别 复制代码 1 //1 2 Class sonClass = Son.class; 3 //2 4 Class aClass = Maint.class.getClassLoader().loadClass("com.Son"); 5 //3 6 Class bClass = Class.forName("com.Son"); 复制代码 代码2: 其实这种方法调运的是:ClassLoader.loadClass(name, false)方法 参数一:name,需要加载的类的名称 参数二:false,这个类加载以后是否需要去连接(不需要linking) 代码:3: 其实这种方法调运的是:Class.forName(className, true, ClassLoader.getCallerClassLoader())方法 参数一:className,需要加载的类的名称。 参数二:true,是否对class进行初始化(需要initialize) 参数三:classLoader,对应的类加载器 其中1、2都是将.class文件加载到JVM中,得到Class对象,但是还没有连接(Link),静态代码块不会执行; 代码3得到Class对象并且已经完成初始化,静态代码块会执行。( Class.forName("com.mysql.jdbc.Driver");//通过这种方式将驱动注册到驱动管理器上)。 1、2、3都不会执行对象的构造函数。 五、思考:区别 是类(Class)初始化执行的方法,是对象初始化执行的方法(构造函数); 详情见:JVM思考-init和clinit区别https://www.cnblogs.com/java-zzl/p/9899856.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信