目录

ThasBlog

学无止境

X

JAVA 内存区域

image.png

内存区域(逻辑)

线程私有

image.png

  • 虚拟机栈

    栈是方法执行的容器, 每个方法执行时都会创建一个栈帧, 然后压入栈中.

    栈有容量限制, 如果栈帧创建过多或者多大, 栈容量不够用, 就会抛出 StackOverflow 异常.

    通过 -Xss 设置单个线程的栈的默认大小限制(180K - 1G, 默认1M). 如果需要提高栈的深度, 应当扩大该参数. 但是由于操作系统对栈有限制, 如果栈的默认大小过大, 所能创建的线程数量也会降低, 如果需要扩大线程数量, 应当减小 -Xss 的限制(也可以减小 -Xmx 堆内存限制)

    栈帧的构成:

    • 局部变量表

      Java 编译成字节码后, 是没有手动命名的变量( a,b 这些字母)的, 所以的变量都是存放局部变量表中, 变量的赋值需要, 需要压入操作数栈, 再经由操作数栈弹出到局部变量表的执行位置

      局部变量表只会存放基本数据类型和对象引用

    • 操作数栈

      Jvm 并没有累加器和寄存器的概念, 所有这些底层设备都抽象成了操作数栈, 运算时将待运算的操作数入栈, 再执行计算指令即可.

      操作数可以类比物理内存结构中的 CPU 缓存.

    • 动态链接

      除了静态方法和私有方法, 其他方法的调用目标地址是不确定的, 需要等对象确定后才能知道具体的调用地址, 这些不确定的地址就是动态链接.

      属性的赋值是调用内部特殊方法实现的, 可以看做私有方法.

    • 返回地址

      方法执行完成后的返回地址

  • 本地方法栈

    类似栈, 用于执行native方法

  • 线程计数器

    每个线程都有一个线程计数器, 用于存放当前线程当前执行的行号(或内存地址), 线程上下文切换后可以根据行号继续执行.

共享

  • image.png
    GC 管理区域

    • 新生代

      • eden

        默认 8/10

      • suvivor

        默认 1/10 , 有两个, 用于复制回收算法

    • 老年代

      默认 2/3大小

  • 方法区

    Jvm 字节码载入内存后的存放区域, Java 7 物理实现是永久代, Java 8 改为元空间.

    常量池:

    存放类地址, 方法地址, 预定义的字符串常量

    • 静态常量池

      静态常量池指 Class 字节码文件中的一块区域, 存放所有常量和符号引用. 比如类文件在没有加载到方法区前, 类地址和方法并不知晓; 字符串会送至常量池用于共享, 它本身是引用地址, 这个也是不确定的, 会用符号表示放在常量池.

    • 运行时常量池

      静态常量池会加载至内存中的方法区形成运行时常量池, 特殊的是, 运行时常量池中原本的符号引用会随着类加载替换为直接引用.

      注意: 数值类型并不是常量. 数值类型包装时本质上是调用 valueOf() 方法, -128-127 的整形会使用缓存.

      字符串常量, 在 Java 8 后放在堆中. Java 7 intern() 方法创建新的常量送至常量池并返回常量池的地址, 可能和原来的字符串地址不一致; Java 8 后将引用放置常量池.

直接内存

非虚拟机管理的内存.

Jvm 参数

https://www.cnblogs.com/xiaoliu66007/p/6186479.html

-Xmx3550m:设置JVM最大可用内存为3550M。
-Xms3550m:设置JVM促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmn2g:设置年轻代大小为2G。整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
-XX:MaxPermSize=16m:设置持久代大小为16m。

-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6
-XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。默认为15,但是会动态调整。

标题:JAVA 内存区域
作者:thas
地址:https://thas.cc/articles/2020/10/11/1602426963457.html