5.剑指JavaOffer-JVM

Java如何跨平台?


image.png

JVM如何加载.class


image.png

谈谈反射:反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能叫做java反射机制。
反射例子:


image.png
image.png

类加载classloader:


image.png

双亲委派模型:


双亲委派

实现自定义类的ClassLoader,重写findClass 实现defineClass:

    private String path;
    private String classLoaderName;

    public MyClassLoader(String path, String classLoaderName) {
        this.path = path;
        this.classLoaderName = classLoaderName;
    }

    //用于寻找类文件
    @Override
    public Class findClass(String name) {
        byte[] b = loadClassData(name);
        return defineClass(name, b, 0, b.length);
    }

    //用于加载类文件
    private byte[] loadClassData(String name) {
        name = path + name + ".class";
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            in = new FileInputStream(new File(name));
            out = new ByteArrayOutputStream();
            int i = 0;
            while ((i = in.read()) != -1) {
                out.write(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();
    }
}

测试:

public class ClassLoaderChecker {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader m = new MyClassLoader("/Users/baidu/Desktop/", "myClassLoader");
        Class c = m.loadClass("Wali");
        System.out.println(c.getClassLoader());
        System.out.println(c.getClassLoader().getParent());
        System.out.println(c.getClassLoader().getParent().getParent());
        System.out.println(c.getClassLoader().getParent().getParent().getParent());
        c.newInstance();
    }
}

类的加载方式:
隐式加载:new
显示加载:loadClass和forName


image.png

Class.forName得到的class是已经初始化完成的
数据库驱动加载就是使用Class.froName(“com.mysql.jdbc.Driver”),有静态代码块,一加载的时候就会调用。

Classloder.loaderClass得到的class是还没有链接的

内存模型

程序计数器:



线程独立的,只为Java方法计数,依赖计数器的值取字节码指令

虚拟机栈和本地方法栈(Native那些):
本地方法栈和虚拟机栈所发挥的作用是很相似的,它们之间的区别不过是 虚拟机栈为虚拟机执行Java方法(字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务
Java栈也称作虚拟机栈(Java Vitual Machine Stack),也是常说的栈。Java栈是Java方法执行的内存模型。Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池(运行时常量池的概念在方法区部分会谈到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。栈也是线程私有的。


image.png
image.png

七个栈帧,load入栈,store出栈。
当递归过深的时候就会出发stackoverflowerr异常。

image.png

元空间MetaSpace 永久代PermGen

参数调优

虚拟机栈会扩容 至Xmx 一般把Xms和Xmx设置为一样,当发生扩容时,会发生内存抖动。

堆和栈的区别
image.png
false和false

false和true

回来再看看

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容