ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JVM总结1:jvm结构图 类加载器 方法区 栈

2020-10-27 10:01:09  阅读:154  来源: 互联网

标签:JVM Person 结构图 person jvm 方法 加载


jvm是什么:

java virtual machine,程序在编译时,通过jvm编译为字节码(class文件),这样可以跨平台执行,在执行时是由jvm解释执行的。

 

jvm体系图:

 

 

 

 

 

类加载器:

运行时,.class文件由类加载器加载到内存中成为Class类的一个实例,每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。

有三种类加载器,他们之间有继承关系,加载的类的范围也不一样。

 

 

这是继承关系:

 

 

 以下代码可以用来测试一下类加载器

public class TestClass {
    public static void main(String[] args) {
        Car car = new Car();
        System.out.println(car.getClass());
        System.out.println(car.getClass().getClassLoader());
        System.out.println(car.getClass().getClassLoader().getParent());
        String a="dfsf";
        System.out.println(a.getClass().getClassLoader());
    }
}

 

双亲委派机制:

  • 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。
  • 每一个层次的类加载器都是如此。因此,所有的加载请求最终都应该传送到顶层的启动类加载器中。
  • 只有当父加载器反馈自己无法完成这个加载请求时(搜索范围中没有找到所需的类),子加载器才会尝试自己去加载。
  • 为了保护安全,不能用户自己随便写一个String类,结果就加载了这个类。

Native方法

 

 

在类中突然看到这样的代码,像接口或者抽象类里面的,没有实现。 带了native关键词,代表java作用范围达不到了,回去调用c语言库。

这种start0方法就进了本地方法栈---本地方法接口--本地方法库

JNI java native interface

native还是用的少的--底层,硬件,掌握概念即可,企业开发中少见  

PC寄存器

 

 方法区

《深入理解Java虚拟机》书中对方法区(Method Area)存储内容描述如下:它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。 在 JDK7 及以前,习惯上把方法区,称为永久代。JDK8开始,使用元空间取代了永久代。JDK 1.8后,元空间与永久代最大的区别在于: 元空间不在虚拟机设置的内存中,而是使用本地内存 static,final,方法,常量池 那么不带static的方法放在哪个区域呢? 通过实例引用调用实例方法的时候,先从方法区中对象的实际类型信息找,找不到的话再去父类类型信息中找。

 

 

对象的加载过程

public class Person{
    int age;
    String name;
    public void walk() {
        System.out.println("我正在走路。。。。");
    }
}
然后我们测试一下:
public class Test {
    public static void main(String[] args) {
        Person person = new Person();
        person.name = "java的架构师技术栈";
        person.age = 18;
        person.walk();
    }
}
我们分析一下这个过程

第一步,JVM去方法区寻找Test类的代码信息,如果有直接调用,没有的话使用类的加载机制把类加载进来。同时把静态变量、静态方法、常量加载进来。这里加载的是(“冯冬冬的IT技术栈”,“冯XX”);这是因为字符串是常量,age中的18是基本类型。

第二步,jvm进入main方法,看到Person person=new Person()。首先分析Person这个类,同样的寻找Person类的代码信息,有就加载,没有的话类加载机制加载进来。同时也加载静态变量、静态方法、常量(“我正在走路。。。”)

第三步,jvm接下来看到了person,person在main方法内部,因而是局部变量,存放在栈空间中。

第四步,jvm接下来看到了new Person()。new出的对象(实例),存放在堆空间中。

第五步,jvm接下来看到了“=”,把new Person的地址告诉person变量,person通过四字节的地址(十六进制),引用该实例。 是不是有点晕,别着急,画个图看一下。

第六步,jvm看到person.name = “冯冬冬的IT技术栈”;person通过引用new Person实例的name属性,该name属性通过地址指向常量池的"冯冬冬的IT技术栈"。

第七步,jvm看到person.age = 18; person的age属性是基本数据类型,直接赋值。

第八步,jvm看到person.walk(); 调用实例的方法时,并不会在实例对象中生成一个新的方法,而是通过地址指向方法区中类信息的方法。走到这一步再看看图怎么变化的

 

虚拟机栈

栈和队列原来老是有点弄得晕,现在看这个比喻挺好的。

栈就是,先放进去当然后面才能拿出来。

队列就是先进先出了FIFO(first in first out)。

栈是跟线程的,生命周期和线程同步。每个线程对应一个独立的stack。线程结束,栈内存就释放,对于栈不存在垃圾回收问题。

 

 这个栈的过程,栈走完之后会弹出栈。

栈是由这些栈帧组成的,一个方法对应一个栈帧。

 

 方法中的基本类型变量是放在这个本地变量表中的,非基本类型会在这放一个引用(指向内存地址)。

JVM堆中存的是对象。JVM栈中存的是基本数据类型和JVM堆中对象的引用。一个对象的大小是不可估计的,或者说是可以动态变化的,但是在JVM栈中,一个对象只对应了一个4btye的引用(JVM堆JVM栈分离的好处:))。

为什么不把基本类型放JVM堆中呢?因为其占用的空间一般是1~8个字节——需要空间比较少,而且因为是基本类型,所以不会出现动态增长的情况—— 长度固定,因此JVM栈中存储就够了,如果把他存在JVM堆中是没有什么意义的(还会浪费空间,后面说明)。可以这么说,基本类型和对象的引用都是存放在 JVM栈中,而且都是几个字节的一个数,因此在程序运行时,他们的处理方式是统一的。但是基本类型、对象引用和对象本身就有所区别了,因为一个是JVM栈 中的数据一个是JVM堆中的数据。最常见的一个问题就是,Java中参数传递时的问题。

 

StackOverflow,栈溢出错误。如果你无限压栈就会,例如递归调用方法层数太多。

 

标签:JVM,Person,结构图,person,jvm,方法,加载
来源: https://www.cnblogs.com/take-it-easy/p/13881455.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有