• 巩固java(二)----JVM堆内存结构及垃圾回收机制


    前言:
           我们在运行程序时,有时会碰到内存溢出(OutOfMemoryError)的问题,为了解决这种问题,我们有必要了解JVM的内存结构和垃圾回收机制。


    正文:

           1.JVM堆内存结构


            JVM主要管理两种类型的内存,堆内存和非堆内存。
            “java虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此分配,堆是java虚拟机启动时创建的”,对内存就是代码可及的地方。
           “java虚拟机除堆外的内存称为非堆内存”,是java虚拟机自己内部所需的内存。

            JVM堆内存的结构如下图所示:
            
       JVM堆内存分为新域,旧域,永久域三个部分。
       我们下面通过程序申请内存的过程了解各个区域的作用:
       1.当我们在程序中通过new创建一个对象时,会为该对象在堆的新域的eden中分配一块内存(eden用来存放新生对象);
       2.执行1时,如果eden中的内存不够,JVM将试图释放eden中的不活跃对象(此时叫:minor collection),如果eden的内存仍不足以存放新创建的对象,则将eden中剩余的活跃对象转移到救助空间中;
       3.当旧域的空间足够时,救助空间的对象会被转移到旧域(所以survivor相当于eden与旧域的中间交换区);
       4.当旧域空间不够时会释放空间(此时叫:major collection)
       5.如果survivor和旧域无法存放eden复制过来的对象,导致eden无法为新对象分配内存,会报:OutOfMemoryError

       2.JVM垃圾回收

         在上面的申请内存过程中已经涉及到了垃圾回收,下面在详细说一下。
         先说一下新域的垃圾回收过程:
         在新域中有两个survivor作为中转,两个survivor相对的作为from和to逻辑区域,其中from区域用来保存对象,to区域保持为空。
         当eden区域不足以支持新增对象时,会执行垃圾回收(GC),eden中的对象和from区域的对象转移到to区域,当to区域满时,一部分对象转移到old区域,即旧域。
         
    GC执行结束后eden和from区域被清空,这是from区域和to区域进行交换。

       关于这里为什么JVM要用两个survivor来做中转,一说是:“对象在两个survivor之间来回移动,知道他们足够老,能够放入保存期较长的old即旧域”。
                

    3.解决堆溢出问题

    上面我们了解了JVM堆内存的结构和GC,当我们遇到java.lang.OutOfMemoryError: Java heap space这个异常时,可以通过重新设定参数来解决。
        JVM在启动时会自动自动设置Heap Size的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可 进行设置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。 提示:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。 提示:Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。



    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    访问控制
    静态方法
    类的特殊属性
    Ubuntu Linux 安装配置 MySQL
    Ubuntu16.04 18.04 安装rabbitmq 配置、使用详细教程
    E: The package lists or status file could not be parsed or opened.
    Linux 安装jsoncpp
    gpgkeys: protocol `https’ not supported
    pch文件中调试模式的使用
    ios UITableview 刷新某一个cell 或 section
  • 原文地址:https://www.cnblogs.com/dingxiaoyue/p/4931764.html
Copyright © 2020-2023  润新知