jvm堆 笔记4

本地方法库 native Method

一个java调用非java代码的接口。没有方法实现体

存在原因

  1. java应用需要与外部环境交互
  2. 与操作系统交互 通过本地方法 用java实现java实现了 jre 的与底层系统的交互
  3. sun解释器 用c实现

本地方法栈

管理本地方法的调用
1. 线程私有
2. 允许被实现成 固定 或动态

权限不受虚拟机控制

  1. 本地方法可以通过本地方法接口 来访问虚拟机内部的运行时数据区
  2. 使用本地处理器中的寄存器
  3. 直接从本地内存的多种分配任意数量的内存

  1. 一个jvm实例只有一个堆内存
  2. java 堆去在jvm启动的是偶即被创建,空间也确定
  3. 堆内存大小可以调节
  4. 在方法结束后,堆中的对象不会马上 被移除,仅仅在垃圾回收的时候才会被移除
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kEag0huJ-1605518030825)(en-resource://database/5200:1)]

内存细分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qOJ0H4ey-1605518030828)(en-resource://database/5202:1)]

-Xms 用来设置堆空间 初始大小
-X jvm运行参数
ms memory start
-Xmx 用来设置堆 最大内存大小

默认

初始内存 物理内存/64
最大内存 物理/4

年轻代和老年代

  1. 对象分为两类
    1. 生命周期短
    2. 周期长

在这里插入图片描述

-XX:NewRatio=2 新生代1 老年代2
-XX:NewRatio=4 新生代1 老年代4
默认 2

在HotSpot 中 eden空间和另外两个Survivor空间缺省所占的比例是8:1:1

  • 几乎所有java对象都是从 eden区
  • 绝大部分的java对象的销毁都在新生代进行
  • 垃圾回收频繁在新生区收集,很少在老年去收集,

在这里插入图片描述
在这里插入图片描述

对象分配过程

分配问题
垃圾回收问题

Minor GC 、Major GC 、 Full GC

major full gc 暂停时间在 minor gc

大部分回收指新生代
回收分两大类型:

  1. 部分收集 partial gc
    新生代收集
    老年代收集
    只有cms gc 会有收集老年代的行为
    混合收集 mixed gc
    收集整个 新生代以及部分老年代
    只有 g1 GC有
  2. 整堆收集 full gc
    收集整个java堆 方法区

年轻代gc Minor Gc

当年轻代 空间不足时 出发 eden满 survior 满不会触发
minor gc会引发 stw 暂停用户线程, 等垃圾回收结束 程序线程才恢复运行

老年代Gc (Major Gc 、FUll GC)

major gc 会比minor gc 慢10倍以上 stw时间更长
major gc 内存还不足 oom

full gc触发 情况
  1. 调用system.gc()
  2. 老年代空间不足
  3. 方法区空间不足
  4. 通过minor gc 进入老年代的平均大小大于老年代的可用内存
  5. eden 区 survivor space0(from space)区向survivor space1 (to space 复制时) 对象大小大于 to space 可用内存 则吧 该对象 转存到老年代,且有可用内存

内存分派策略

  1. 优先分配到eden
  2. 大对象直接分配到老年代
  3. 长期存活的的对象分派到老年代
  4. 动态对象年龄判断
    1. 如果survivor中相同年龄的所有对象大小总和大于survivor空间的一半 年龄大于等于 改年龄的对象 直接进入老年代,
  5. 空间分配担保
    1. -XX:HandlePromotionFailure

为对象分配过程TLAB

从内存模型分析,对eden进行划分,jvm为每个线程分配了一个私有缓存区域
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qYBboQ1z-1605518030860)(en-resource://database/5212:1)]
默认空间占eden空间1%
默认开启
一旦tlab空间分配失败 ,jvm就会尝试着通过使用枷锁机制确保数据操作的原子性

在这里插入图片描述

堆区是线程共享区域
由于对象实例的创建在jvm中非常频繁,因此在并发环境下从堆去中划分内存空间是线程不安全的
为避免多个线程操作同一地址,需要枷锁等机制,进而影响分配速度

堆是对象分配存储的唯一选择吗

所有对象实例都是创建在堆上。
intern字符串的缓存和静态变量分配到元数据区,

堆外存储技术

在逃逸分析后发现,一个对象没有逃逸出方法的话,被优化成栈上分配

逃逸分析

有效减少java程序中同步负载和内存堆分配压力的跨函数全局数据里分析算法

当一个对象在方法中被定义以后,对象只在内部使用 没有发生逃逸
被外部引用,eg调用参数 发生逃逸

好处

减少java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法

优化策略

栈上分配

将堆分配转化为 栈分配
JIT编译器在编译期间根据逃逸分析的结果,发现如果一个对象并没有逃逸出方法的话,可能被优化为栈上分配

同步省略

如果一个对象发现只能从一个线程被访问到,可以不考虑同步

  • 线程同步代价很高,后果是并发性和性能
  • 在动态编译同步块的时候,jit编译器可以借助逃逸分析来判断同步块的锁对象是否只能够被一个线程访问而没有发布到其他的线程,如果没有 会取消这部分代码同步 锁消除

分离对象或标量替换

有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分,可以不存储在内存(堆),而存储在cpu寄存器(java -》栈)

jit阶段 编译器通过逃逸分析,经过jit优化,就会把这个对象拆解成若干个其中包含若干成员变量替代,

标量

无法分解成更小的数据
java 原始的数据类型

聚合量

因为可以分解成其他聚合量 和标量

指令

-XX:+EliminateAllocations 开启标量替换 允许将对象打散分配到栈上
-XX:UseAdaptivesSizePolicy 关闭自适应的内存分配策略
-XX:SurvivorRatio=8 设置edent 与Survivor的比例 默认8
-XX:NewRatio 设置新生代与老年代的比例 默认2
-Xmn 设置新生代的空间大小
-Xms 初始堆空间
-Xmx 最大堆空间
jps 当前程序运行的进程
jstat -gc 9228 查看jvm gc 统计信息
-XX:+PrintFlagsInitial 查看所有参数初始
-XX:+PrintFlagsFinal 查看所有参数最终值
-server 启动server 才可以开启逃逸分析
-XX:+DoEscapeAnalysis 逃逸分析开启
-XX:+PrintEscapeAnalysis 查看逃逸分析筛选结果
-XX:+PrintGCDetails
jinfo -flag NewRatio 进程号
-XX:MaxTenuringThreadshold= 晋升老年代次数 默认15
-XX:HandlePromotionFailure 空间分配担保
-XX:UseTLAB 开启tlab空间
-XX:TLABWasteTargetPercent 设置tlab空间占用eden空间的百分比

调优工具

jdk 命令行
Eclipse: memory analyzer tool
jconsole
visualvm
jprofiler
java flight recorder
GcViewer
GC easy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值