栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JVM运行时数据区(堆内存)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JVM运行时数据区(堆内存)

一、基本介绍
  • 栈管运行,堆管存储
一一对应
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, 但是存在垃圾回收过程 



  • 特殊情况
3. 常见GC
  • JVM在进行GC时,并非每次都对上三个内存区域一起回收
  • 大部分回收都是指新生代
  • 垃圾回收的时候,会有STW, 导致用户线程的暂停(标记清除)
HotSpot VM, 垃圾回收分为两类:   部分收集(Partial GC) 和 整堆收集(Full GC)

1. 部分收集: 不是完整收集整个JAVA堆中的垃圾收集
   1.1 Minor GC:  收集新生代(Eden, S0, S1)
   1.2 Major GC:  收集老年代
    - CMS GC  会单独收集老年代
    
   1.3 Mixed GC: 收集整个新生代以及部分老年代
   - 目前只有G1 GC会有这样的行为

2. 整堆收集(Full GC): 收集整个java堆和方法区
3.1 Minor GC
- 当年轻代Eden空间不足时,就会触发Minor GC, S0/S1满时不会触发
- Java对象大多朝生夕死, Minor GC非常频繁, 回收速度比较快
- Minor GC会引发STW, 暂停其他用户线程
3.2 Major GC
- 发生在老年代的GC
- Major GC触发时,一般至少触发一次Minor GC
   1. 先尝试Minor GC, 如果空间还是不足,则出发Major GC
- Major GC 的速度一般比Minor GC慢10倍以上, STW的时间会更长
- Major GC后,内存还不足,就 OOM
3.3 堆分代思想
  • 为什么要进行堆内存分代
优化GC 性能
1. 如果没有分代,那所有对象都在一块, gc 时候需要所有区域扫描
2. 分代后
   - 朝生夕死的对象,存放在新生代
   - 生命周期长的对象,方法老年代

# 感觉和数据库分表的思想有点像啊

4. 内存分配策略
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/843231.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号