JVM知识分享(二)之内存模型简介

 JVM系列文章

JVM知识分享(一)

JVM知识分享(二)

JVM知识分享(三)

JVM知识分享(四)

JVM知识分享(五)

目录

前言

一、程序计数器

二、虚拟机栈& 本地方栈

三、堆

四、方法区

总结


前言

本次给大家介绍下JMM虚拟机内存模型中的一些概念。


先上一张图,给大家总体看下。

一、程序计数器

  1. 是当前线程所执行的字节码的行号指示器,指向虚拟机字节码指令的位置。
  2. 被分配了一块较小的内存空间。
  3. 针对于非Native方法:是当前线程执行的字节码的行号指示器。
  4. 针对于Native方法:则为undefined。
  5. 每个线程都有自己独立的程序计数器,所以,该内存是线程私有的。
  6. 这块区域是唯一一个在虚拟机中没有规定任何OutOfMemoryError情况的区域。

二、虚拟机栈& 本地方栈

虚拟机栈为执行Java方法服务的,是描述方法执行的内存模型。本地方法栈是为native方法服务的,就不做展开了。

  1. 栈是线程私有的内存空间。每次函数调用的数据都是通过栈传递的。在栈中保存的主要内容为栈帧。它的数据结构就是先进后出。
  2. 每当函数被调用,该函数就会被入栈,每当函数执行完毕,就会执行出栈操作。而当前栈顶,即为正在执行的函数。
  3. 每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、帧数据区等信息。

栈桢操作如下图所示:

三、堆

运行时数据区,几乎所有的对象都保存在java堆中。

  1. Java堆是完全自动化管理的,通过垃圾回收机制,垃圾对象会被自动清理,而不需要显示地释放。
  2. 堆是垃圾收集器进行GC的最重要的内存区域。
  3. Java堆可以分为:新生代(Eden区、S0区、S1区)和 老年代。
  4. 在绝大多数情况下,对象首先分配在eden区,在一次新生代GC回收后,如果对象还存活,则会进入S0或S1,之后,每经历过一次新生代回收,对象如果存活,它的年龄就会加一。当对象的年龄达到一定条件后,就会被认为是老年代对象,从而进入老年代。

四、方法区

逻辑上的东西,是JVM的规范,所有虚拟机必须遵守的。

  1. 是JVM 所有线程共享的、用于存储类信息,例如:类的字段、方法数据、常量池等。
  2. 方法区的大小决定了系统可以保存多少个类。
  3. JDK8之前——永久代。
  4. JDK8及之后——元空间。

永久代

指内存的永久保存区域,主要存放Class和Meta(元数据)的信息,Class在被加载的时候被放入永久区域,它和存放实例的区域不同,GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常。

  1. 如果系统使用了一些动态代理,那么有可能会在运行时生成大量的类,从而造成内存溢出。所以,设置合适的永久代大小,对于系统的稳定性是至关重要的。
  2.  -XX:PermSize设置初始永久代大小。例如:-XX:PermSize=5m
  3. -XX:MaxPermSize设置最大永久代大小,默认情况下为64MB。例如:-XX:MaxPermSize=5m

元空间

在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。

  1. 元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用堆外的直接内存。因此,与永久代不同,如果不指定大小,默认情况下,虚拟机会耗尽所有的可用系统内存。
  2. -XX:MaxMetaspaceSize设置元空间默认初始大小。例如:-XX:MetaspaceSize=40m
  3. 设置最大元数据空间。例如:-XX:MaxMetaspaceSize=40m

总结

以上就是本次的分享,希望能给有需要的朋友帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值