一、概述
一个类是如何到在jvm里面,到到底干了哪些事情。
二、类的生命周期
首先简要讲下类的生命周期:
类加载包括:初始化之前的所有步骤。加载:通过一个类的全限定名来获取定义此类的二进制字节流。将这个字节流所代表的静态存储结构转化为方法区运行的数据结构。在java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据访问的入口。
验证:保证Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机的自身的安全。
准备:正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中分配。
解析:虚拟机将常量池内的符号引用替换为直接引用的过程。
初始化:真正开始执行类中定义的java程序代码。执行类构造器<clinit>()方法的过程。
三、类加载器
四、破坏双亲模型的类加载器只能影响类的 加载阶段。其他阶段都不能影响判断两个类是否相等,同一个类加载器加载的类且类路径相同。java设计者弄出了双亲委派模型(对于保证java程序的稳定性很重要)
实现代码在:protected synchronized Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{// First, check if the class has already been loadedClass c = findLoadedClass(name);if (c == null) {try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.c = findClass(name);}}if (resolve) {resolveClass(c);}return c;}
第一次:
由于双亲模型是在jdk1.2之后引入的,所以之前的就不是双亲模型,之前ClassLoader的子类唯一目的是重写loadClass(),为了向前兼容,之后这个方法还是protected的。为了保证双亲模型,增加了一个findClass()类,子类实现此类即可。
第二次:
自身的模型的缺陷,如果 父类加载器加载的类需要调用子类加载器需要加载的类呢?为此引入了,线程上下文加载器。(每个代码都在线程中运行的,可以通过)publicClassLoader getContextClassLoader()Thread有一个类加载器:/* The context ClassLoader for this thread */privateClassLoader contextClassLoader;
第三次:
是由于用户动态追求加载导致的。如:代码热替换、模块热部署。典型的算:OSGI技术。每一个程序模块(Bundle)都有一个自己的类加载器,当需要更换一个Bundle时,就把Bundle直接替换掉。