堆和堆参数调优

一、再议永久代和方法区

  上一篇提到:在8版本以前,JVM采用堆空间的一部分实现方法区,这部分堆空间被称为“永久代”,由于类的结构信息和运行时常量池是放在方法区的,使用永久代实现方法区容易导致堆内存溢出。在8版本推出以后,Java采用了堆外内存即本机物理内存实现方法区,我们把这部分空间称为“元空间”。

  

分享图片

 

  

分享图片

 

二、堆内存

  众所周知,当线程new了一个对象后,对象的引用变量存放在栈针中,而对象本身存储在堆内存中,如果大量的对象存储在堆内存而无法被GC回收,那么将导致OOM错误,那么堆空间多大呢?GC的工作流程是什么样呢?可以设置堆空间大小吗?可以选择GC工作方式吗?

  1、堆内存结构以及GC过程:

  

分享图片

 

 

   新生代空间:老年代空间 = 1 : 3,而其中新生代中Eden : from :to区域=8:1:1

  新生代是实例对象诞生的区域,也是绝大多数实例对象消亡的区域,新生代分为两个区域:Eden区和Survivor区,Survivor区又分为SurvivorFrom区和SurvivorTo区。所有的对象都是在Eden区被new出来的。当Eden区满时会触发第一次GC,把幸存下来的对象会被 “复制”到From区 。如果Eden区再此触发GC,此时GC会扫面Eden区和From区,对这两个区域进行垃圾回收,经过这次回收后还存活的对象会直接复制到To区,并为这些对象的“年龄”+1。 

  在完成复制后,清空Eden和From区的对象。完成清空后,将From去和To去对换,那个区域为空那个区域作To区,所以这两块区域的大小是一样的。完成互换后,下一次触发GC继续扫描Eden和From区,并再次幸存对象放入To区,清空Eden和From区,然后交换From和To,谁空谁作To,为下一次垃圾回收扫描做准备。当一个对象在From区To区来回复制,“年龄”不断增长始终无法被回首时,当“年龄”达到MaxTenuringThreshold的默认值15,此对象就会进入老年代。

  2、堆内存调优

  Java虚拟机在启动时,初始内存为本机内存的1/64,当此内存不够实用,虚拟机会尝试获取更多的内存空间,但是默认情况下最大可使用内存为本机内存大额1/4。当然你可以通过配置虚拟机参数来改变虚拟机占用内存的情况,在生产环境中,建议配置初始内存空间大小和最大可使用空间大小相同,以避免进程争夺内存资源时造成的卡顿。

  可以使用如下代码查看虚拟机占用空间的大小:

public class Demo1 {
    public static void main(String[] args) {
        System.out.println(Runtime.getRuntime().availableProcessors());//查看逻辑处理器

        long maxMemory = Runtime.getRuntime().maxMemory();//返回Java虚拟机可以使用的最大内存量
        long totalMemory = Runtime.getRuntime().totalMemory();//返回Java虚拟机中的内存总量

        System.out.println("-Xmx: MAX_MEMORY = " + maxMemory + "(字节)、" + (maxMemory / (double)1024/1024) + "MB");
        System.out.println("-Xms: TOTAL_MEMORY = " + totalMemory + "(字节)、" + (totalMemory / (double)1024/1024) + "MB");
    }
}
4
-Xmx: MAX_MEMORY = 1886912512(字节)、1799.5MB
-Xms: TOTAL_MEMORY = 128974848(字节)、123.0MB

  3、配置虚拟机占用内存大小

  IDEA:

  

分享图片

  STS

  

分享图片

 

 

   参数:

  -Xms:设置初始(start)分配内存大小  -Xmx:设置最大(max)分配内存大小  -XX:+PrintGCDetails:输出详细的GC处理日志

  4、制造错误、日志分析

  为了更快地导致内存溢出,我将-Xms和-Xmx都设置成10m。

public class Person {
    private String name;
    byte[] bytes = new byte[10*1024*1024];
    public Person(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Demo1 {
    public static void main(String[] args) {
        while(true){
            Person person = new Person(UUID.randomUUID().toString());
        }
    }
}
[GC (Allocation Failure) [PSYoungGen: 2048K->504K(2560K)] 2048K->696K(9728K),0.0032340 secs] [Times: user=0.00 sys=0.00,real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1289K->504K(2560K)] 1481K->812K(9728K),0.0006781 secs] [Times: user=0.00 sys=0.00,real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 504K->488K(2560K)] 812K->852K(9728K),0.0006038 secs] [Times: user=0.00 sys=0.00,real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 488K->0K(2560K)] [ParOldGen: 364K->774K(7168K)] 852K->774K(9728K),[Metaspace: 4020K->4020K(1056768K)],0.0075233 secs] [Times: user=0.00 sys=0.00,real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] 774K->774K(9728K),0.0003232 secs] [Times: user=0.00 sys=0.00,real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 774K->753K(7168K)] 774K->753K(9728K),0.0113270 secs] [Times: user=0.02 sys=0.00,real=0.01 secs] 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.qlu.juc.Person.<init>(Person.java:5)
    at com.qlu.juc.Demo1.main(Demo1.java:8)
Heap
 PSYoungGen      total 2560K,used 99K [0x00000000ffd00000,0x0000000100000000,0x0000000100000000)
  eden space 2048K,4% used [0x00000000ffd00000,0x00000000ffd18d90,0x00000000fff00000)
  from space 512K,0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K,0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 ParOldGen       total 7168K,used 753K [0x00000000ff600000,0x00000000ffd00000,0x00000000ffd00000)
  object space 7168K,10% used [0x00000000ff600000,0x00000000ff6bc510,0x00000000ffd00000)
 Metaspace       used 4051K,capacity 4572K,committed 4864K,reserved 1056768K
  class space    used 454K,capacity 460K,committed 512K,reserved 1048576K

  ①

 

分享图片

 

 

 在分配内存是,我指定了虚拟机最大占用内存为10m,而此处仅新生代和老年代就占用了近乎10m,足以证明元空间并不使用虚拟机内存实现,而是使用了本地内存。

  ②分析日志:内存占用

分享图片

 

 

   ③分析日志:GC日志

[GC (Allocation Failure) [PSYoungGen: 1289K->504K(2560K)] 1481K->812K(9728K),real=0.00 secs] 

[GC (Allocation Failure)
指出了GC类型,GC负责收集新生代的Eden和From区域,Allocation Failure表示空间分配失败
[PSYoungGen: 1289K->504K(2560K)]
1289k表示YoungGC收集前新生代内存占用情况,504k表示YoungGC后新生代内存占用情况,此轮GC释放了785k内存。(2560)表示新生代总占用空间大小
1481K->812K(9728K),0.0006781 secs]
1481k表示YoungGC收集前堆的使用情况,812k表示YoungGC收集之后堆空间的使用情况,次轮GC释放了669k内存。(9728k)表示堆空间的总大小,还有10m-9728k被栈、程序计数器、本地方法栈占用。
0.0006781secs表示YoungGC耗时。
[Times: user=0.00 sys=0.00,real=0.00 secs]
user:YoungGC用户耗时,sys:YoungGC 系统耗时,real:YoungGC实际耗时

[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 774K->753K(7168K)] 774K->753K(9728K),real=0.01 secs] 

[Full GC (Allocation Failure)
指出了GC类型,Full GC负责收集老年代区域,Allocation Failure表示空间分配失败
[PSYoungGen: 0K->0K(2560K)]
新生代:GC前后Young区内存占用情况
[ParOldGen: 774K->753K(7168K)]
老年代:GC前老年代的占用情况,可以看出基本没有回收,7168k表示老年代内存空间大小
774K->753K(9728K),
GC前后堆的占用情况以及对的总内存大小
[Metaspace: 4020K->4020K(1056768K)],0.0113270 secs]
元空间占用情况和元空间大小,Full GC耗时
[Times: user=0.02 sys=0.00,real=0.01 secs]
user:YoungGC用户耗时,sys:YoungGC 系统耗时,real:YoungGC实际耗时。

  当老年代空间执行了Full GC后发现依然无法进行新对象的保存(空间分配)即Allocation Failure,就会报出“OutOfMemoryError”。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 连接 连接池产生原因 连接池实现原理 小结 TEMPERANCE:Eat not to dullness;drink not to elevation.节制
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 一个优秀的工程师和一个普通的工程师的区别,不是满天飞的架构图,他的功底体现在所写的每一行代码上。-- 毕玄 1. 命名风格 【书摘】类名用 UpperCamelC
今天犯了个错:“接口变动,伤筋动骨,除非你确定只有你一个人在用”。哪怕只是throw了一个新的Exception。哈哈,这是我犯的错误。一、接口和抽象类类,即一个对象。先抽象类,就是抽象出类的基础部分,即抽象基类(抽象类)。官方定义让人费解,但是记忆方法是也不错的 —包含抽象方法的类叫做抽象类。接口
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket一、引子文件,作为常见的数据源。关于操作文件的字节流就是 —FileInputStream&amp;FileOutputStream。
作者:泥沙砖瓦浆木匠网站:http://blog.csdn.net/jeffli1993个人签名:打算起手不凡写出鸿篇巨作的人,往往坚持不了完成第一章节。交流QQ群:【编程之美 365234583】http://qm.qq.com/cgi-bin/qm/qr?k=FhFAoaWwjP29_Aonqz
本文目录 线程与多线程 线程的运行与创建 线程的状态 1 线程与多线程 线程是什么? 线程(Thread)是一个对象(Object)。用来干什么?Java 线程(也称 JVM 线程)是 Java 进程内允许多个同时进行的任务。该进程内并发的任务成为线程(Thread),一个进程里至少一个线程。 Ja
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket在面向对象编程中,编程人员应该在意“资源”。比如?1String hello = &quot;hello&quot;; 在代码中,我们
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 这是泥瓦匠的第103篇原创 《程序兵法:Java String 源码的排序算法(一)》 文章工程:* JDK 1.8* 工程名:algorithm-core-le
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 一、父子类变量名相同会咋样? 有个小故事,今天群里面有个人问下面如图输出什么? 我回答:60。但这是错的,答案结果是 40 。我知错能改,然后说了下父子类变
作者:泥瓦匠 出处:https://www.bysocket.com/2021-10-26/mac-create-files-from-the-root-directory.html Mac 操作系统挺适合开发者进行写代码,最近碰到了一个问题,问题是如何在 macOS 根目录创建文件夹。不同的 ma
作者:李强强上一篇,泥瓦匠基础地讲了下Java I/O : Bit Operation 位运算。这一讲,泥瓦匠带你走进Java中的进制详解。一、引子在Java世界里,99%的工作都是处理这高层。那么二进制,字节码这些会在哪里用到呢?自问自答:在跨平台的时候,就凸显神功了。比如说文件读写,数据通信,还
1 线程中断 1.1 什么是线程中断? 线程中断是线程的标志位属性。而不是真正终止线程,和线程的状态无关。线程中断过程表示一个运行中的线程,通过其他线程调用了该线程的 方法,使得该线程中断标志位属性改变。 深入思考下,线程中断不是去中断了线程,恰恰是用来通知该线程应该被中断了。具体是一个标志位属性,
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want需求 项目在设计表的时候,要处理并发多的一些数据,类似订单号不能重复,要保持唯一。原本以为来个时间戳,精确到毫秒应该不错了。后来觉得是错了,测试环境下很多一
纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 加微信:bysocket01
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want.文章Points:1、介绍RESTful架构风格2、Spring配置CXF3、三层初设计,实现WebService接口层4、撰写HTTPClient 客户
Writer :BYSocket(泥沙砖瓦浆木匠)什么是回调?今天傻傻地截了张图问了下,然后被陈大牛回答道“就一个回调…”。此时千万个草泥马飞奔而过(逃哈哈,看着源码,享受着这种回调在代码上的作用,真是美哉。不妨总结总结。一、什么是回调回调,回调。要先有调用,才有调用者和被调用者之间的回调。所以在百
Writer :BYSocket(泥沙砖瓦浆木匠)一、什么大小端?大小端在计算机业界,Endian表示数据在存储器中的存放顺序。百度百科如下叙述之:大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加
What is a programming language? Before introducing compilation and decompilation, let&#39;s briefly introduce the Programming Language. Programming la
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket泥瓦匠喜欢Java,文章总是扯扯Java。 I/O 基础,就是二进制,也就是Bit。一、Bit与二进制什么是Bit(位)呢?位是CPU
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocket一、前言 泥瓦匠最近被项目搞的天昏地暗。发现有些要给自己一些目标,关于技术的目标:专注很重要。专注Java 基础 + H5(学习) 其他操作系统,算法,数据结构当成课外书博览。有时候,就是那样你越是专注方面越