jvm学习笔记(1)——java虚拟机内存区域

一、java内存区域:

    

1、程序计数器(线程私有):

    内存中较小的内存空间,可以当做当前线程所执行字节码的行号指示器。如分支、循环、跳转、异常处理、线程恢复都需要依赖这个计数器完成。

2、java虚拟机栈(线程私有):

    也就是我们通常所说的“堆栈”中的栈。栈是由一个个栈帧组成的。栈帧中存放局部变量表、各种基本的数据类型(boolean、byte、char、short、int、float、long、double)、对象引用、方法返回地址等。当线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压栈。当方法执行完毕之后,便会将栈帧出栈。所以递归调用容易出现StackOverflowError异常,即线程请求的栈深度超过了虚拟机允许的最大深度。

    每个线程分配的栈的大小是设置的(-Xss来设置),栈的基本单位是栈帧。所以栈帧所占空间越大,栈的深度就越小,反之亦然。简单的可以理解为:栈的大小=栈帧大小平均值*栈的深度

3、本地方法栈(线程私有):

    与虚拟机栈发挥的作用类似,只不过本地方法栈使用的本地方法服务(Native方法服务)。

4、java堆(所有线程共享):

    在虚拟机启动时创建,存放对象的实例。

    从GC回收的角度来说,可细分为新生代、老年代。

    更细致的把新生代拆分为Eden空间、From Survivor空间、To Survivor空间等。

    可以通过-Xms和-Xmx控制分配的堆的大小。当堆内没有足够的内存完成实例分配,且到达堆的大小上限,会抛出OutOfMemoryError异常,即我们经常说的OOM。

5、方法区(所有线程共享):

    存放已被虚拟机加载的类的信息、常量池、静态变量、即时编译器编译后的代码(JIT)、64位系统上类压缩指针等数据。

    逻辑上虽为java虚拟机堆的一部分,为了和java堆区分开来,又称为Non-Heap(非堆)。

    在jdk1.8之前方法区通过“永久代”(PermGen)来实现,在jdk1.8及以后废弃,采用“元空间”(MetaSpace)来实现。最大的区别是永久代是在jvm虚拟机上分配的内存,而元空间是分配的本地内存。可通过-XX:MetaspaceSize-XX:MaxMetaspaceSize配置元空间分配的大小和上限。

    更细致的拆分MetaSpace(元空间)、CodeCache(代码缓存区,主要存放JIT编译生成的二进制代码)、CompressedClassPointSpace(压缩类指针空间,主要用于64位系统上类压缩指针)。

二、总结:

    整理下,输出个思维导图。

参考资料:

《深入理解JAVA虚拟机》

    

猜你喜欢

转载自blog.csdn.net/luoliang2012/article/details/83146616
今日推荐