java虚拟机运行时数据区

一、区域分类:

线程私有数据区:栈(虚拟机栈、本地方法栈)、程序计数器。

线程共享数据区:堆、方法区。

说明:sun hotspot虚拟机,  虚拟机栈、本地方法栈这两区域合一。

二、线程私有

1.程序计数器

        可以看作是当前线程执行字节码的行号指示器。多线程是通过线程轮流切换并分配处理器执行的时间方式来实现的。因此,程序计数器可以保证切换后恢复到正确的执行位置。每条线程都有自己独立的程序计数器,互相独立,各不影响。

       如果执行Native方法,计数器值为空(undefined)。

场景如下:Thread A 执行到代码第5行,切换到Thread B执行, 执行后再次切换到Thread A,接着从第5行执行,能正确的记住这个位置,并执行,是程序计数器的功劳。

2.虚拟机栈:

       服务于java方法(字节码) 。

        java方法执行的内存模型:每个方法在执行的同时都会创建栈帧,栈帧存储的是:局部变量表,操作数栈,动态链接,方法出口等。栈,先进后出。

       局部变量表:存放编译器可以的各种基本数据类型(8大基本类型)、对象引用(reference类型,可理解为句柄)、returnAddress类型(指向一条字节码指令的地址)。这一块也是我们最关注的。

     操作数栈:可以理解为栈的工作区,操作局部变量表中的数据。

     动态链接:将符号引用解析为直接引用的过程。

     方法出口:目前我的理解是,记住方法的出口,相当一个标记。可以精准的知道方法何时出栈。

// 执行时创建栈帧,先入栈执行,执行完后出栈。
// 入栈 testA -> testB(),出栈 testB()->testA
public void testA(){
    int a = 1;   // 存储在局部变量表中。(线程私有)
    User user = new User(); // 引用(句柄)存储在局部变量表(线程私有),对象本身存储于堆中(线程共享)。
    testB();
}

3.本地方法栈:

      服务于native方法。

三、线程共享

1.堆

       虚拟机启动是创建,是虚拟机管理的最大内存区域。几乎所有的对象都在堆上分配内存。是垃圾收集器管理的主要区域(因为该区域比较大并且存有大量对象)。

       堆可以细分:新生代,老年代;在细分有Eden空间、From Survivor空间,To Survivor空间。

       堆中可以划分出多个线程私有的分配缓存区(Thread Local Allocation Buffer. TLAB)。该区域可以在用于精准分配对象内存,防止多线程情况下,内存覆盖。除了TLAB还有其他方式可以保证该点。 

       堆中区域内部的划分,目的是为了更高效的回收垃圾。、

举例理解TABL:

        线程A,线程 B同时需要在堆上给对象分配内存.

        1.如果没有TLAB:线程A 分配的内存,可能会被线程B分配的内存覆盖掉。(没有同步机制)

         2.如果有TLAB:在各自的缓冲区分配内存。

2.方法区

     存储被虚拟机加载的类信息、常量、静态变量、即时编译器(JIT)编译后的代码等数据。

     2.1 运行是常量池:方法区一部分,用于存储编译器生成的各种字面量和符号引用。这部分内容在类加载后进入

常量池。

四、直接内存

       不是虚拟机运行时的数据区部分。也不是虚拟机规范中的一部分。

       该内存不会受到,java堆大小的限制,但是会受到本机内存的限制。

       如jdk 1.4 加入的NIO,可以直接使用Native函数直接分配对外内存。

 《深入理解java虚拟机》 (第二版)   学习之路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值