JVM运行时数据区

JVM运行时数据区,第1张

一、基本介绍
  • 栈管运行,堆管存储
一一对应
1. 一个java进程对应一个jvm实例
2. 一个jvm实例对应一个Runtime类
3. 一个Runtime类对应一个堆空间
1. 基本概念
1. Java堆区在Jvm启动后就会被创建,其空间大小就确定了
2. JVM管理的最大的一块内存空间, 空间大小可以调节
3. 堆可以出于物理上不连续的内存空间,但在逻辑上它应该视为连续的
4. 所有的线程共享java堆 
   细分:(线程私有的缓冲区(Thread Local Allocaation Buffer(TLAB), 堆主存储))
2. 核心概念
1. 所有的  对象实例 和 数组 都在堆上分配内存

2. 数组和对象永远不会存储在栈上,因为栈帧中只保存引用,这个引用
   指向对象或者数组在堆中的位置

3. 方法结束后,堆中对象不会马上被移除,仅在垃圾收集的时候才会被移除

4. 堆,是GC执行的重点区域

3. 内存细分
  • 逻辑上分为三部分: 新生代,老年代,元空间
新生代: Young Generation Space(Eden space,  Survivor spaca)

老年代: Tenure Generation Space

元数据区:Meta Space
二、堆空间大小 1. 基本设置
  • Java堆区用于存储Java对象实例,堆的大小在JVM启动的时候就用已经设定好了
# 1. 参数设置
-Xms:256k
   1. 表示堆区的起始内存(新生代+老年代)
   2. -X: jvm的参数
   3. ms: memory start 

-Xmx: 1028k
   1. 表示堆区的最大内存
   2. mx:memory max


# 2.异常
- 堆区的内存大小超过了-Xmx指定的最大内存时候, 就会抛出 OutOfMemoryError

OutOfMemoryError: Java heap space

# 3.最佳实践
-Xms和-Xmx配置相同的值? Yes!
-Xms1000M -Xmx1000M

能够在java垃圾回收机制处理完堆区后,不需要重新分隔计算堆区的大小,提高性能
(避免不必要的扩缩容,增大系统压力)


# 4. 默认情况
初始内存大小:  物理电脑内存大小/64
最大内存大小:  物理电脑内存大小/4
package com.nike.erick.d06;

public class Demo05 {
    public static void main(String[] args) {
        //  初始内存,
        long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
        //  最大内存
        long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;

        System.out.println("初始JVM堆内存:" + initialMemory + "M");
        System.out.println("最大JVM堆内存:" + maxMemory + "M");

        System.out.println("本地物理内存:" + initialMemory * 64 / 1024 + "G");
        System.out.println("本地物理内存:" + maxMemory / 1024 * 4 + "G");
    }
}
2. 新生代和老年代
1. 存储在JVM中的java对象被划分为两类
     1.1 生命周期短的瞬时对象,创建和消亡都很快
     1.2 生命周期比较长,极端情况下和JVM的生命周期一样(Runtime类)

2. JVM堆区划分
     2.1 年轻代: Eden, Survivor0和Survivor1(from区和to区)
     2.2 老年代
2.1 内存大小
  • 默认配置
  • 一般不会去修改, 如果该项目中的很多的对象时间都很长,则考虑修改
  • 大多数的java都是在Eden中被new出来的, 同时也会在Eden中被销毁
1. 新生代和老年代堆中比例

-XX:NewRation=2:  新生代占1,老年代占用2
-XX:NewRation=4:  新生代占1,老年代占用4

# 如何查看参数
jps                                  : 得到端口号
jinfo -flag NewRatio 40402           : 得到比例 

2. 新生代老年代按照指定数字分配
-Xmn100M                     显示指定,以这个为准


3. 新生代中Eden 和另外两个Survivor默认比例是。 8:1:1

-XX:SurvivorRatio=8                 :调整为 8:1:1

#  如何查看
jps                                  : 得到端口号
jinfo -flag SurvivorRatio 40402      : 查看比例 
2.2 对象分配过程
1. 新对象在Eden创建,如果满了(可达性算法),则触发    Minor GC(Young GC)
2. 回收不用的对象, 有用的对象复制到 S0中,并加上版本号
     
3. 第二次Eden满了后,继续触发 Minor GC
4. 将Eden中存活对象和S0的对象放到S1中,其中S0的也去判断哪些可用,可用的版本号加1 
    ( 谁空放谁 )

5. from区到to区域时候,如果版本号达到15(阈值),则会Promotion, 放在老年代 
   -XX:MaxTenuringThreshold=15:   手动设置阈值
   假如Survivor满了,同时没有达到阈值,也会放在老年代

tips: Survivor不会触发minor gc, 但是存在垃圾回收过程 



  • 特殊情况

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/756403.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-30
下一篇 2022-04-30

发表评论

登录后才能评论

评论列表(0条)

保存