专栏首页爱明依Java 运行时的内存划分

Java 运行时的内存划分

Java 运行时的内存划分

image

程序计数器

记录当前线程所执行的字节码行号,用于获取下一条执行的字节码。

当多线程运行时,每个线程切换后需要知道上一次所运行的状态、位置。由此也可以看出程序计数器是每个线程私有的。

虚拟机栈

虚拟机栈由一个一个的栈帧组成,栈帧是在每一个方法调用时产生的。

每一个栈帧由局部变量区操作数栈等组成。每创建一个栈帧压栈,当一个方法执行完毕之后则出栈。

  • 如果出现方法递归调用出现死循环的话就会造成栈帧过多,最终会抛出 StackOverflowError
  • 若线程执行过程中栈帧大小超出虚拟机栈限制,则会抛出 StackOverflowError
  • 若虚拟机栈允许动态扩展,但在尝试扩展时内存不足,或者在为一个新线程初始化新的虚拟机栈时申请不到足够的内存,则会抛出 OutOfMemoryError

这块内存区域也是线程私有的。

Java 堆

Java 堆是整个虚拟机所管理的最大内存区域,所有的对象创建都是在这个区域进行内存分配。

可利用参数 -Xms -Xmx 进行堆内存控制。

这块区域也是垃圾回收器重点管理的区域,由于大多数垃圾回收器都采用分代回收算法,所有堆内存也分为 新生代老年代,可以方便垃圾的准确回收。

这块内存属于线程共享区域。

方法区(JDK1.7)

方法区主要用于存放已经被虚拟机加载的类信息,如常量,静态变量。 这块区域也被称为永久代

可利用参数 -XX:PermSize -XX:MaxPermSize 控制初始化方法区和最大方法区大小。

元数据区(JDK1.8)

JDK1.8 中已经移除了方法区(永久代),并使用了一个元数据区域进行代替(Metaspace)。

默认情况下元数据区域会根据使用情况动态调整,避免了在 1.7 中由于加载类过多从而出现 java.lang.OutOfMemoryError: PermGen

但也不能无线扩展,因此可以使用 -XX:MaxMetaspaceSize来控制最大内存。

运行时常量池

运行时常量池是方法区的一部分,其中存放了一些符号引用。当 new 一个对象时,会检查这个区域是否有这个符号的引用。

直接内存

直接内存又称为 Direct Memory(堆外内存),它并不是由 JVM 虚拟机所管理的一块内存区域。

有使用过 Netty 的朋友应该对这块并内存不陌生,在 Netty 中所有的 IO(nio) 操作都会通过 Native 函数直接分配堆外内存。

它是通过在堆内存中的 DirectByteBuffer 对象操作的堆外内存,避免了堆内存和堆外内存来回复制交换复制,这样的高效操作也称为零拷贝

既然是内存,那也得是可以被回收的。但由于堆外内存不直接受 JVM 管理,所以常规 GC 操作并不能回收堆外内存。它是借助于老年代产生的 fullGC 顺便进行回收。同时也可以显式调用 System.gc() 方法进行回收(前提是没有使用 -XX:+DisableExplicitGC 参数来禁止该方法)。

值得注意的是:由于堆外内存也是内存,是由操作系统管理。如果应用有使用堆外内存则需要平衡虚拟机的堆内存和堆外内存的使用占比。避免出现堆外内存溢出。

常用参数

image

通过上图可以直观的查看各个区域的参数设置。

常见的如下:

  • -Xms64m 最小堆内存 64m.
  • -Xmx128m 最大堆内存 128m.
  • -XX:NewSize=30m 新生代初始化大小为30m.
  • -XX:MaxNewSize=40m 新生代最大大小为40m.
  • -Xss=256k 线程栈大小。
  • -XX:+PrintHeapAtGC 当发生 GC 时打印内存布局。
  • -XX:+HeapDumpOnOutOfMemoryError 发送内存溢出时 dump 内存。

新生代和老年代的默认比例为 1:2,也就是说新生代占用 1/3的堆内存,而老年代占用 2/3 的堆内存。

可以通过参数 -XX:NewRatio=2 来设置老年代/新生代的比例。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • `OutOfMemoryError` 问题相信很多朋友都遇到过,相对于常见的业务异常(数组越界、空指针等)来说这类问题是很难定位和解决的...

    OutOfMemoryError 问题相信很多朋友都遇到过,相对于常见的业务异常(数组越界、空指针等)来说这类问题是很难定位和解决的。

    爱明依
  • Java虚拟机内存溢出原因分析以及解决方案

    在Java虚拟机规范的描述之中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有可能发生内存溢出OutOfMemoryError(OOM)异常的可能。

    爱明依
  • java 内存模型的基础(二)

    如果线程A与线程B之间要通信的话,必须要经历下面2个步骤。 1 线程A把本地内存A中更新过的共享变量刷新到主内存中去。 2 线程B到主内存中去读取...

    爱明依
  • 今咱们来聊聊JVM 堆外内存泄露的BUG是如何查找的

    JVM的堆外内存泄露的定位一直是个比较棘手的问题。此次的Bug查找从堆内内存的泄露反推出堆外内存,同时对物理内存的使用做了定量的分析,从而实锤了Bug的源头。笔...

    美的让人心动
  • 解Bug之路-记一次JVM堆外内存泄露Bug的查找

    用户1263954
  • win32应用程序性能测试-内存篇

    本文主要讲述windows平台下应用程序性能测试的内存相关的知识,通过本文了解内存基本原理和分析内存占用问题。 一、内存是什么? 1内存分为物理内存和虚拟内存 ...

    腾讯移动品质中心TMQ
  • Android应用性能优化——内存优化(内附一个内存泄露优化实例)

    自动管理内存和回收机制,垃圾回收器负责回收程序中已经不使用,但是仍然被各种对象占用的内存,将程序员从繁重、危险的内存管理工中解放出来。

    trampcr
  • 虚拟内存详解

    究其原因,监控系统计算的可用内存算法有偏差,他只关注了计算机的“实际”内存,忽略了计算机的虚拟内存。

    bisal
  • 软件性能测试(连载9)

    Linux内核给每个进程都提供了一个独立的虚拟地址空间,并且这个地址空间是连续的。Linux的空间又分为内核空间和用户空间,在32位中,内核空间占1G,用户空间...

    小老鼠
  • 故障分析 | MySQL OOM 故障应如何下手

    前阵子处理这样一个案例,某客户的实例 mysqld 进程内存经常持续增加导致最终被 OOM killer。作为 DBA 肯定想知道有哪些原因可能会导致 OOM(...

    爱可生开源社区

扫码关注云+社区

领取腾讯云代金券