JAVA堆栈

最近在看JAVA虚拟机规范,谈下自己对java堆栈的理解

java虚拟机内存分为:栈、本地方法栈、堆、程序计数器、方法区

JAVA栈

java栈中的运行单位是栈帧。

class ActivityThread {

    public void main() {

            int index = 0;

            Student student = new Student();

    }

}

上面一段代码很简单,讲下其运行过程:

1:java虚拟机查找方法区中是否已经加载了ActivityThread的字节码信息,如果没有,则加载其字节码并保存到方法区。将静态成员变量保存到方法区的静态存储区(此时会完成静态成员变量的初始化,只有一次初始化);将常量保存到常量池中;多态的动态链接也发生在这一步

2:确定堆区域要调用的main()方法,然后java虚拟机会到方法区中找到main方法的字节码,生成对应的栈帧,压栈运行。

PS:第二步栈帧也是要占内存的,其内存大小在创建栈帧时就已经确定,并且在运行过程中不会发生变化。原因就是栈帧中有一个局部变量表,其中的所有类型并且所占空间在编译时都已经确定。虚拟机将所有数据类型定义为u1类型,long和double定义为u2类型,u1占4个字节,u2占8个字节,都是以u1和u2为单位操作的。

3:index和值0,会被存放到栈帧的局部变量表中。执行Student student = new Student();这一行时,如果方法区没有Student信息,java虚拟机加载Student。student是对象的别名,存放的是new Student()对象在堆中的起始地址

4:方法运行结束,销毁栈帧

5:栈和程序计数器都是线程独立的,即每个线程都有自己的栈和程序计数器

6:栈大小包括指定栈深度和动态申请两种,分别可能发生栈溢出或者OOM

JAVA堆

堆是用来存储对象的。有很多很多种垃圾回收器,前面有篇博客介绍了JAVA对象的创建和回收,这里就不在多说。

对象销毁

一个对象的销毁要经过两次标记,第一次标记:GC ROOT不能到达时会把对象标记为死对象,然后将该对象放入F-Queue列,java虚拟机会创建线程单独处理F-Queue中的对象,此时会调用对象的finalize()方法,在此方法中,可以将该对象复制给其他引用,这样就可以把该对象再次加入引用链。第二次标记:如果在后续的GC过程中,如果GC ROOT再次不能到达此对象,对象会被第二次标记为死对象,然后直接回收掉。

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

推荐阅读更多精彩内容

  • 1 JVM栈 (Java Virtual Machine Stacks) 在介绍JVM栈之前,我先了解一下 栈帧 ...
    轝巐阅读 10,414评论 0 2
  • Java 虚拟机屏蔽了与具体操作系统平台相关的信息,使得 Java 语言编译程序只需生成在 Java 虚拟机上运行...
    寻梦的尕柳阅读 4,312评论 0 11
  • 在介绍堆栈之前简单说下JVM的内存结构,一共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分: 栈: 线程...
    高岳_bdf5阅读 4,857评论 0 1
  • 问:请分别写出一段堆和栈溢出的 Java 代码片段? 如上可见,递归调用可以导致栈溢出,不断的创建对象可以导致堆溢...
    Little丶Jerry阅读 4,298评论 0 0
  • 概述 先Copy一个概念:JVM是基于堆栈的虚拟机。JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Ja...
    dylanhuang88阅读 6,804评论 0 53