JVM-对象内存分配与回收细节问题

2023-10-27

对象内存分配与回收细节问题

1. 禁用System.gc()

System.gc():会显示直接触发Full GC,同时触发老年代和新生代进行回收。而一般情况是我们认为,垃圾回收时自动进行的,无需手动触发。频繁的垃圾回收对系统性能造成较大影响。可以使用-XX:+DisableExplicitGC,则禁用显示GC,使得System.gc()等价于一个空函数。

2. System.gc()使用并发回收

默认情况下,即时System.gc()生效,它会使用传统的Full GC的方式回收整个堆,而会忽略参数中断的UseG1GCUseConcMarkSweepGC

使用-XX:+ExplicitGCInvokesConcurrent后,System.gc()这种显示GC才会使用并发发的方式进行回收。否者无论是否启用CMS和G1,都不会进行并发回收。

3. 并行GC前额外触发的新生代GC

对于并回收器(使用UseParallelGC或者UseParallelOldGC),在每一次Full GC之前都会伴随一次新生代的GC

故使用并发回收器时,使用System.gc()会触发两次GC,这样做的目的是先将新生代进行一次收集,避免将所有回收工作同时交给一次Full GC进行,这样可以缩短一次停顿时间。

-XX:-ScavengeBeforeFullGC 可以关闭上面这个特性,默认的情况下,这个是true的。

4. 对象何时进入老年代

4.1 老年对象进入老年代

初创的对象在eden区域中存放


当对象每经过一次GC,对象的年龄就会加一,当对象的年龄达到一定的值时,对象就可以晋升为老年代的对象。这个值可以通过MaxTenuringThreshold设定,默认值是15。

package com.liuyao;

import java.util.HashMap;
import java.util.Map;

/**
 * Created By liuyao on 2018/4/18 15:56.
 */
public class MaxTenuringThreshold {
    public final static int _1M=1024*1024;
    public final static int _1K=1024;

    public static void main(String[] args) {
        Map<Integer,byte[]> map=new HashMap<>();
        for (int i = 0; i < 5*_1K; i++) {
            byte[] bytes=new byte[_1K];
            map.put(i,bytes);
        }

        for (int i = 0; i < 17; i++) {
            for (int j = 0; j < 270; j++) {
                byte[] bytes=new byte[_1M];
            }
        }
    }
}

运行参数:

-Xmx1024M -Xms1024M -XX:MaxTenuringThreshold=10 -XX:+UseSerialGC -XX:+PrintCommandLineFlags  -XX:+PrintGCDetails

修改运行参数为:

-Xmx1024M -Xms1024M -XX:MaxTenuringThreshold=10 -XX:TargetSurvivorRatio=15 -XX:+UseSerialGC  -XX:+PrintCommandLineFlags  -XX:+PrintGCDetails

MaxTenuringThreshold是对象晋升的充分非必要条件,即达到这个值,对象必然晋升,而未达到该年龄,对象也可能晋升。事实上,对象的实际晋升年龄,是由虚拟机在运行时自行判断的。

确定对象晋升的另外一个重要参数是:TargetSurvivorRatio,它用于设置survivor区的目标使用率,默认是50,即如果survivor区在GC超过50%的使用率,就可能会使用一个较小的age作为晋升年龄

综上:对象的实际晋升年龄是根据survivor区的使用情况动态计算得来的,而MaxTenuringThreshold只是表示这个年龄的最大值

4.2 大对象进入老年代

除了年龄以外,对象的体积也会影响对象的晋升。如果一个对象很大,新生代无论eden区还是survivor区都没办法容乃对象,那么对象将直接分配在老年代。

PretenureSizeThreshold:它用来设置对象直接晋升到老年代的阈值,单位值字节。只要对象大于该值,就会绕过新生代,直接分配到老年代中。该参数只对ParNew收集器有效,对ParallelGC无效,该值的默认值是0,表示不设定该值的大小,一切由运行情况而定。

5. 在TLAB上分配对象

TLAB 全称叫做Thread Local Allocation Buffer 线程本地分配缓存,是一个线程专用的内存分配区域。为加速对象分配而生的。

TLAB本身占用了eden区的空间,在TLAB启用的情况下,虚拟机会为每一个Java线程分配一块TLAB空间。

由于TLAB空间一般不会太大,因此大对象无法在TLAB上面分配,总是会直接分配在堆上,TLAB由于空间小,总是容易装满,假如一个100KB的空间,如果已经使用80KB,现在要分配一个30KB的对象,有两种办法:
1. 废弃当前的TLAB,将会浪费20KB空间
2. 将这30KB的对象直接分配在堆上,希望以后有小于20KB的对象分配在TLAB上

虚拟机内部会维护一个refill_waste的值,当强求大于refill_waste时,会选择在堆上分配,若小于该值,将废弃当前TLAB,新建TLAB来分配对象。这个值可以通过-XX:TLABRefillWasteFraction来设置,它表示TLAB中允许产生这种浪费的比例,默认值是64,即表示可以使用约1/64的TLAB空间作为refill_waste。

默认情况下,TLAB和refill_waste都是会在运行时不断调整的,使系统运行达到最优。

-XX:+PrintTLAB:查看TLAB使用情况
-XX:-ResizeTLAB:禁用自动调整TLAB大小
-XX:TLABSize:手工指定TLAB大小

6. 方法finalize()对垃圾回收的影响

Java提供了类似C++中析构函数的机制——finalize()函数

该函数允许在子类中被重载,用于在对象回收时进行资源的释放。但尽量不要使用它,主要原因有:

  1. finalize()可能导致对象复活
  2. finalize()执行时间是没有保障的,它完全由GC线程决定,极端情况下,若不发生GC,则finaliz()将没有机会执行。
  3. 一个糟糕的finalize()会严重影响GC的性能。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JVM-对象内存分配与回收细节问题 的相关文章

随机推荐

  • BOF——Bag-of-Featrures

    本文主要介绍 BOF Bag of Featrures 的原理及其应用 1 1 引言 文档分类领域有一种模型称为词袋 Bag of words 模型 它是自然语言处理与信息检索过程中的一种简化模型 在这种模型中 文本 段落或文档 被视为忽略
  • Docker之网络:容器通信的模式与技术

    Docker的网络基础 默认网络模式 特殊的几种网络模式 容器和宿主机的通信方式 容器与外部主机的通信方式 文章目录 Docker的网络基础 一 Docker默认的原生网络 bridge桥接 二 host模式 三 none模式 四 Dock
  • 代码审计总结

    目录 概述 一 代码审计 1 1什么是代码审计 1 2为什么要执行代码审核 1 3代码审计的好处 二 代码审计流程 2 1代码检查方法 2 2代码检查项目 2 3编码规范 2 4代码检查规范 2 5缺陷检查表 2 6代码审计复查 2 7代码
  • Linux工具 Ansible

    Linux工具 ansible Ansible是一个运维管理工具 可以减少一些重复的配置 比如有几百台主机需要进行相似的配置时或者对所有主机进行某些软件的版本升级时 如果是人工一台一台的配置是非常慢的 也容易出错 毕竟人精力有限 而这个An
  • PowerShell 美化(谁不想要一个好看的终端呢)

    PowerShell 美化 安装powershell Scoop 安装 Oh My Posh 安装 字体设置 应用主题 花里胡哨的折腾 bushi 多种主题任君挑选 安装powershell 地址 https github com Powe
  • neo4j官方示例数据库

    官方示例数据库 CREATE TheMatrix Movie title The Matrix released 1999 tagline Welcome to the Real World CREATE Keanu Person name
  • param.grad为 None或者TypeError: unsupported operand type(s) for *: ‘float‘ and ‘NoneType‘

    在学习李沐的动手学深度学习 从零开始实现softmax回归中 我跟着敲完代码 发现无法运行 报错入如下 TypeError Traceback most recent call last Cell In 72 line 3 1 num ep
  • 小程序蓝牙传输二维码

    有个需求 蓝牙要显示二维码 需要得到二维码的位图 点阵图 矩阵图 实现思路 1 获得canvas的二维码图片 要求为64px乘64px 2 获得二维码的图片 然后解析像素数组 获得像素的二进制状态码 3 将二进制状态码转化为byte数组 然
  • PCIE专题学习——1.0

    PCIE基础概念 一 1 PCIe的概念 PCIe是一种全双工 差分 端对端 串行告诉接口协议 PCI是并行处理的机制 差分可以提高传输的稳定性 全双工意味着发送端在发送的同时 也可以接收 问题在于串行会比并行处理快吗 当然不一定 这和系统
  • RuntimeError: The Session graph is empty. 和no Attribute““解决方法

    问题产生的原因 无法执行sess run 的原因是tensorflow版本不同导致的 tensorflow版本2 0无法兼容版本1 0 解决办法 添加行 tf compat v1 disable eager execution 无法执行se
  • JAVA 通过POI实现Excel从单元格选择下拉选项

    发生情景 最近使用到了模板导出功能 最开始使用的是hutool的POI工具 但是做下拉列表的时候 addSelect方法报错 问题 Excel在添加自定义下拉数据的时候 输入内容不能大于255个字符 这在做一些简单的下拉选项时没有问题 但是
  • 数论整理之算数基本定理de变形

    D Sigma Function 这道题一看到就和上一道题很像 以为也是算数基本定理的考查 做了一下 发现能过样例 tle tle的思路 经过多次验算 就是发现幂的规律吧 只要存在一个pi ei都为奇数的pi ei 就能使sum为偶数 素因
  • R语言中的quantile()函数

    在R语言中取百分位比用quantile 函数 下面举几个简单的示例 1 求某个百分位比 gt data lt c 1 2 3 4 5 6 7 8 9 10 gt quantile data 0 5 50 5 5 gt quantile da
  • 【ES】原生es的复杂查询

    原生es的复杂查询 相关依赖 复杂查询概述 外层查询 SearchSourceBuilder 类 外层查询概述 对查询结果进行分页 对查询结果进行排序 对查询结果字段进行过滤 对查询结果进行聚合 求年龄的最大值 根据年龄进行分组 内层查询
  • 关于两个页面用params传数据,刷新后数据消失的解决

    通常我们在两个页面传数据时 一般会采用params query 或者将数据用vuex localStorage sessionStorage存储起来 然后方便其他页面调用数据 但是params和vuex有一个不好的地方就是只要我们在接受数据
  • R6-1 给定两个均不超过9的正整数a和n,要求编写函数fn(a,n) 求a+aa+aaa++⋯+aa⋯aa(n个a)之和,fn须返回的是数列和函数接口定义:fn(a,n)其中 a 和 n 都是用户传

    给定两个均不超过9的正整数a和n 要求编写函数fn a n 求a aa aaa aa aa n个a 之和 fn须返回的是数列和 函数接口定义 fn a n 其中 a 和 n 都是用户传入的参数 a 的值在 1 9 范围 n 是 1 9 区间
  • python学习笔记---函数【廖雪峰】

    函数 调用函数 函数名其实就是指向一个函数对象的引用 完全可以把函数名赋给一个变量 相当于给这个函数起了一个 别名 gt gt gt a abs 变量a指向abs函数 gt gt gt a 1 所以也可以通过a调用abs函数 1 定义函数
  • UE4内置浏览器支持h264 mp4 视频 编译cef3 3071源码

    转载 原文链接 UE4内置浏览器支持h264 mp4 视频 编译cef3 3071源码 ue4 cef 鸿蒙老道的博客 CSDN博客首先ue4内置的CEF3 浏览器是不支持h264视频的 所以需要我们重新编译CEF内核 然后覆盖旧的版本一
  • 空闲时间不要接私活,要提升自己

    这个话题很纠结 现在社会 有很多人都在利用个人时间兼职赚钱 程序员俗称 接私活 其他行业称作兼职 比如下了班出去跑滴滴 周末兼职抢单送外卖等等 都是普通人很常见的兼职方式 甚至很多技术同行 我听说也有周末去跑滴滴和送外卖的 我觉得很不可思议
  • JVM-对象内存分配与回收细节问题

    对象内存分配与回收细节问题 1 禁用System gc System gc 会显示直接触发Full GC 同时触发老年代和新生代进行回收 而一般情况是我们认为 垃圾回收时自动进行的 无需手动触发 频繁的垃圾回收对系统性能造成较大影响 可以使