三个大阶段
一:装载(三个小阶段)

1.装载:就是读取class文件的字节流,放到jvm中

二:连接(分动态和静态,静态很少使用,下面按顺序三步骤)

1.验证:校验字节的正确性
2.常量池解析:把符号引用替换为指针引用,就是将方法名和类名替换成Class对象的内存地址(类A里有类B,使用类A的时候,先判断A的常量池中是B的class对象,还是B的字符串表示,如果是字符串,则将其替换成Class对象的引用)
3.准备:给静态变量分配内存并且根据相应类型赋默认值(注意此处是默认值)

三:初始化:对静态变量赋指定值,同时执行静态代码块

下面将用代码阐述上述逐个过程

public class MyClass {public static final int a = 1;public int b = 2;public void m1() {m2();}public void m2() {}
}

一.1:将MyClass.class文件通过字节数组读到jvm中
一.2:校验这些字节是不是和jvm定义的一样,假设int在jvm中的机器码是8B,那么此时要校验int a是不是8B a
一.3:使int a=0;
二:在jvm中m1方法肯定不能直接调用m2方法,因为jvm不知道m2是个什么东西,m1调用的应该是m2方法开始的内存地址
三:使int a=1;

关于双亲委派模型
双亲委派存在的意义

1.java的沙箱安全机制,我们自己不能创建java.lang开头的java类
2.避免重复加载类

什么时候需要打破双亲委派

当需要同一个类,并且不同版本的时候
典型的例子就是tomcat的各种类加载器,tomcat实现了许多类加载器,主要目的就是为了实现使用相同名称但是版本又不相同的类

如何自定义类加载器

1.通常实现findclass,本质该方法也会调用loadClass
2.但是如果想打破双亲模型,则覆盖loadClass方法

Java的命名空间(对程序员是透明的,所以我们自己无法定义命名空间名称)
现在有自定义类加载器CL,有一个类A,类A中有一个属性类B,现new两个CL,一个叫CL1,一个叫CL2,它俩都加载类A,返回Class A对象叫Class1和Class2,那么此时Class1!=Class2,而Class1中的B.class也!=Class2中的B.class,由上述结论可知:不同的自定义类加载器,加载的类是相互隔离的,切这些加载的类中引用的类,也是相互隔离的,下面是本结论的代码验证

public class A {public B b = new B();
}
public class B {public void m() {System.out.println(this.getClass().getClassLoader());}
}

将A和B编译成class文件,放到桌面上,下面自定义类加载器

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;public class CL extends ClassLoader {@Overrideprotected Class<?> findClass(String name) {byte[] data = null;// 本自定义类加载器只加载桌面上的class文件// 对name进行处理,如果name是com.aa.A,则nm=A// 如果name是com.abc.MyClass,则nm=MyClassString nm = 对name字符串处理;Path path = Paths.get("C:\\Users\\admin\\Desktop\\" + nm  + ".class");try {data = Files.readAllBytes(path);} catch (Exception e) {e.printStackTrace();}return defineClass(name, data, 0, data.length);}
}

最后一个main方法

public static void main(String[] args) throws Exception {CL c1 = new CL();CL c2 = new CL();Class<?> clazz1 = c1.loadClass("A的全限定名");Class<?> clazz2 = c2.loadClass("A的全限定名");System.out.println(clazz1 == clazz2);//falseField field1 = clazz1.getField("b");Field field2 = clazz2.getField("b");Method m1 = field1.getType().getMethod("m");Object o1 = field1.get(clazz1.getConstructor().newInstance());Method m2 = field2.getType().getMethod("m");Object o2 = field2.get(clazz2.getConstructor().newInstance());m1.invoke(o1);// 值与下面不一样m2.invoke(o2);// 值与上面不一样
}

下面这行代码会打印出null

System.out.println(String.class.getClassLoader());

因为String属于rt包下,由启动类加载器加载(bootstrap classloader),而启动类加载器由c++实现,所以这行代码打印null,因为java中没有启动类加载器

方法区会存放以下类型信息
0.Class对象的引用
1.类型的全限定名
2.直接父类的全限定名(这样就可以找到父类,根据父类可以找到爷爷类)
3.类型标识(用来标识当前类型是类还是接口)
4.访问修饰符(public,abstract,final)
5.直接接口的全限定名列表(就是实现了哪些接口)
6.该类的常量池(字段信息+方法信息),可参考常量池的表现方式
  字段修饰符
  字段类型
  字段名
  方法修饰符
  方法返回值
  方法名
  方法参数的类型集合(按顺序)
  方法的字节码
  操作数栈和局部变量去大小
  常量(其他类如果使用该常量,则其他类会将该常量复制到自己的常量池)
7.ClassLoader的引用(表示哪个类加载器加载的该类)

class对象被回收的条件
class对象被回收的条件必须要同时满足下面3个
1.该class对象不存在实例对象
2.加载该class对象的classloader被回收
3.没有其他地方使用该class对象(通过反射)

Java-虚拟机-类加载(装载连接初始化)相关推荐

  1. 深入Java虚拟机——类型装载、连接(转)

    来自http://hi.baidu.com/holder/item/c38abf02de14c7d31ff046e0 Java虚拟机通过装载.连接和初始化一个Java类型,使该类型可以被正在运行的Ja ...

  2. java虚拟机类加载机制与反射全解

    java虚拟机类加载机制与反射全解 引子: 开门见山,先来个经典面试题:(如果你已经懂了,那么你可以离开了,如果你一脸懵逼,那么请好好看本文,理解透彻很有好处!) class SingleTon {p ...

  3. 面试官,不要再问我“Java虚拟机类加载机制”了

    关于Java虚拟机类加载机制往往有两方面的面试题:根据程序判断输出结果和讲讲虚拟机类加载机制的流程.其实这两类题本质上都是考察面试者对Java虚拟机类加载机制的了解. 面试题试水 现在有这样一道判断程 ...

  4. JAVA虚拟机-类加载机制

    JAVA虚拟机–类加载机制(一) 类加载机制:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接是的Java类型,这就是虚拟机的类加载机制. ...

  5. 深入JVM读书笔记之类装载+连接+初始化

    [u]Java虚拟机通过[b]装载,连接和初始化[/b]一个Java类型,来创建一个新的类型对象[/u],使此类型可以被正在运行中的Java程序所使用.装载就是把二进制形式的Java类型读入Java虚 ...

  6. Java虚拟机类装载的原理及实现

    Java虚拟机类装载的原理及实现 一.引言 Java虚拟机(JVM)的类装载就是指将包含在类文件中的字节码装载到JVM中, 并使其成为JVM一部分的过程.JVM的类动态装载技 术能够在运行时刻动态地加 ...

  7. Java虚拟机类加载机制——案例分析

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  8. Java虚拟机之装载(加载、连接、初始化)

    为什么80%的码农都做不了架构师?>>>    Class类型通常以文件的形式存在(当然,任何二进制流都可以是class类型),只有被java虚拟机装在的class类型才能在程序中使 ...

  9. java 虚拟机类加载 及内存结构

    http://www.jb51.net/article/105920.htm https://www.cnblogs.com/Qian123/p/5707562.html Java类加载全过程 一个j ...

最新文章

  1. MongoDB之conf配置文件详解
  2. 接口测试——postman
  3. 准备把平台挪到linux
  4. ASP.NET把DataTable转成XML文件的函数
  5. 简单入门Javascript正则表达式
  6. 软件测试——0422作业
  7. 手机端召唤Debug
  8. mysql5.7无法启动问题
  9. oracle中的cursor属性有哪些,Oracle学习11:游标(cursor)--显式游标隐式游标、游标四个属性、循环遍历...
  10. Dart云平台-DartPad
  11. 怎样输出矩阵乘积C语言,c语言矩阵相乘
  12. c语言中*在变量的右上角,C语言中变量的声明和定义
  13. wps qt linux,小试牛刀 WPS for Linux beta1文字试用
  14. 买哪个股票稳赚,三类股票,可以买了
  15. RGB颜色与十六进制颜色码
  16. maya导入abc动画_外包过程中的动画重定向以及蒙皮调整经验
  17. 使人疲惫的不是远方的高山,而是你鞋子里的一粒沙子
  18. 计算机免费取名,电脑免费婴儿取名
  19. ubantu查看设备序列号
  20. python播放音乐同步歌词范晓萱_同步_范晓萱_高音质在线试听_同步歌词|歌曲下载_酷狗音乐...

热门文章

  1. 区间内素数的个数(也要用到埃氏算法)
  2. Spring Cloud Stream与RabbitMQ 生产者和消费者位于同一个应用服务
  3. setInterval定时连接后台防止session失效
  4. 转载 Assert断言知识
  5. mac 连接百度云服务器地址,教你怎么在 Mac 下把百度网盘映射到另一个文件夹
  6. 职友集 进化者机器人_麦克风解决方案将发掘交互式机器人的无限潜力
  7. darknet53 作用_YOLOv3 深入理解
  8. mac上投屏android_win10不支持miracast,怎么无线投屏
  9. eclipse 自定义文档注释的作者
  10. java在循环中删除数组元素,在循环Perl中删除数组中的元素