虚拟机---2.加载

金句:

加载不一定初始化,初始化不是实例化

接着1.二进制文件的编译后,会干啥?

我的文章都是记录总结,梳理自己的知识。这篇更多是个人理解和总结。说白就是吹水。。。

文件编译成虚拟机识别的结构,类的表结构;肯定下一步就是加载进虚拟机。

a、先,二进制文件会是啥东西?

类,接口,数组(人家把类当数组用,数组交由虚拟机自己直接生成,无需二进制文件加载 new test [100]跟test 二进制没关系)

public class test {
    static{
        System.out.println("XXXXXX");
    }

    public static void main(String[] args) {
        test[] test = new test[100];
    }
}

输出XXXXXX一次,说明压根没因为new test[100]初始化test,输出一次是main方法搞的

b、啥时候加载?想到啥。不去背,想不全也没关系。

new自己

new自己牵扯父类,前提还没给加载

public class test {
    static{
        System.out.println("XXXXXX");
    }
}

public class testSub extends test{
    static{
        System.out.println("YYYYYY");
    }
    public static void main(String[] args) {
    }
}

jdk反射,java.lang.reflect和java.lang.ref

public class testSub extends test{
    static{
        System.out.println("YYYYYY");
    }
    public void doSomeThing() {
        System.out.println("ZZZZZZ");
    }
    public static void main(String[] args) {        
        Class a = testSub.class;//反射要有二进制类对象
        try {
            a.getMethod("doSomeThing", null).invoke(a.newInstance(), args);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

jdk后面跟上的methodhandler(invokeDynamic,把类的方法匹配交给代码编写者,实现类似js脚本的function识别)

等讲解invokedynamic再举例

main方法主类

public class test {
    static{
        System.out.println("XXXXXX");
    }

    public static void main(String[] args) {
    }
}

以上是五个仅有主动加载。

被动加载,查了书籍,有以下几种

类保函静态终极属性。谁用了他,谁相当于就自己类常量池里面就有了它这个表的符号引用索引。

public class XX{

    static{
        System.out.println("XXXXXX");
    }

public static final int i = 1;//谁用了它,直接它拿进自己的常量池。没必要初始这家伙。

}

数组用了类,但是不会直接初始化它, 但是会加载它

public class test {
    static{
        System.out.println("XXXXXX");
    }

    public static void main(String[] args) {
        test[] test = new test[100];
    }
}

输出XXXXXX一次,说明压根没因为new test[100]初始化test,输出一次是main方法搞的

父子类间,调用了父亲的变量。那不会初始化子类当前类

public class XX{

static{

System.out.println("XXXXXX");

}

public static int yy = 1;

}

public class YY extends XX{

static{

System.out.println("ZZZZZZ");

}

public static void main(){

System.out.println(YY.yy);

}

}

c.楼上确定要加载它,哪怎么加载?

先一个一个步骤来,

第一步,加载,加载二进制文件进方法区(共享数据区),产生一个java.lang.class对象

再说一次,把二进制文件加载进虚拟机规定的通俗叫法方法区,并且new一个这个二进制文件的对象。也就是操作这个类符号表索引的入口。

第二步,链接(验证,准备,解析)

其实,用我们常规思维想,把二进制加载进来,搞了个二进制对象;那怎么玩这里面的二进制符号表索引结构的东西。再说虚拟机安全第一步不就要玩这个玩意。所以第一步肯定是要校验。要不然随便一个东西进来不做校验。校验个啥,校验你这二进制文件是否按照我的游戏规则玩。是否非法。

验证,我想到

语法,回想我们前面一篇,就是魔术是否,按照我们占位个数,顺序,非法字符等。至于还有啥,自己展开联想

准备,开到第一步,类里面的变量全部识别,并简单赋默认值。就算你是int i=123;也要赋0;不急,一步一步

解析,把所有二进制文件的符号索引变成实际类的引用。触发别的类的加载。

第三步,初始化

虚拟机把每个类的初始化工作最终归总为一个方法cinit。它不等同于构造函数。它是把常量池中所有符号引用,变成实际的引用。指向真实的堆地址,偏移地址等。也就是类中静态代码块和成员变量的初始化。跟实例化是两码事。

到这里类的加载就完了。

d.上面说了二进制生成了,那就得加载,加载又是做了什么事情,那回头来想二进制文件是谁把他加载进来,又是按照什么规则加载进来?

这里记一下,启动加载器(c++写的启动类加载器,虚拟机自己的,后面的都不是),扩展加载器(扩展库代码),应用加载器(或自定义加载器,加载你写的应用代码)

规则,双亲委派加载,交给你加载,你得提交你父亲,问他是否能findclass这个玩意。find不到,再轮到你。因为谁家加载的,那这个类二进制class对象跟别人加载的class对象就算是同一个,都不是同一个object;这样在同一个应用中。比如XX二进制文件类,要加载一会交给a加载器,一会交给b加载器,那两个就不是同一个了。要是都交给父亲呢。那就同一个了。

自己的类加载器  

 public static void main(String[] args) {
        new java.lang.ClassLoader() {
            public Class<?> loadClass(String name) throws ClassNotFoundException{
                String fileName = name.substring(name.lastIndexOf("."), +1)+".class";
                java.io.InputStream is = getClass().getResourceAsStream(fileName);
                if(is == null) {
                    return super.loadClass(name);
                }
                try {
                    byte[] b = new byte[is.available()];
                    is.read(b);
                    return defineClass(name,b,0,b.length);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return null;            
            }
        };
    }

猜你喜欢

转载自blog.csdn.net/huangddy/article/details/84262463