浅谈JVM

本文详细介绍了Java虚拟机的内存区域,包括线程私有的程序计数器、虚拟机栈、本地方法栈和线程共享的堆、方法区(元空间),以及对象的创建过程。强调了自动内存管理避免了内存泄漏和溢出,同时解释了对象从类加载检查到执行init方法的步骤。此外,还讨论了对象访问定位的两种方式:句柄和直接指针。
摘要由CSDN通过智能技术生成

        虚拟机自动内存管理机制,不用像C和C++那样为每一个new操作去写对应的delete/free操作,不容易出现内存泄漏和内存溢出问题。

        运行时数据区域:

JDK1.8之前:线程共享:堆,方法区(运行时常量池)。线程私有:虚拟机栈,本地方法栈,程序计数器。线程共享:直接内存。

        线程私有:1.程序计数器:实现代码的流程控制,多线程情况下,记录当前线程执行的位置。2.Java虚拟机栈:由一个个栈帧组成,每个栈帧中都拥有局部变量表,操作数栈,动态链接,方法出口信息。局部变量表中主要存放了编译期可知的各种数据类型,对象引用。每一次的函数调用都会有一个栈帧压入栈,每一个函数结束都有一个栈帧出栈。3.本地方法栈:为虚拟机使用到的native方法服务,本地方法执行时也会再本地方法栈创建一个栈帧,用于存放该本地方法的局部变量表,操作数栈,动态链接,出口信息。

        线程共享:堆:在虚拟机启动时创建,唯一目的就是存放对象实例,几乎所有的对象实例和数组都在这里分配内存,Java堆还可以细分为新生代和老年代。

方法区:用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译的代码等,也被称为永久代。

运行时常量池也是方法区的一部分,class文件中除了有类的版本,接口等信息外,还有常量池表。

        为什么要将永久代替换为元空间呢?整个永久代有一个JVM设置的固定大小,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,虽然元空间可能溢出,但是比原先出现的几率会更小。

        对象的创建:类加载检查--分配内存--初始化零值--设置对象头--执行init方法

step1:类加载检查,虚拟机遇到一条new指令时,将去检查这个指令的参数能否在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程

step2:分配内存,当类加载检查通过后,为新生对象分配内存。

step3:初始化零值,虚拟机将分配到的内存空间都初始化零值,这一步操作保证了对象的实例字段在Java代码中可以不赋初始值就可以使用。

step4:设置对象头:初始化零值之后,虚拟机要对对象进行必要的设置,假如这个对象是哪个类的实例,如何才能找到类的元数据信息,对象的哈希码,对象的GC分代年龄信息等。这些信息存放在对象头中。

step5:执行init方法,从程序员角度来看,init方法未执行,所有字段都还为零,所以一般来说,执行new指令后接着执行init方法,按照程序员意愿初始化对象,这样一个真正的对象才算完全创建出来。

        对象的访问定位:句柄,直接指针

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值