jvm基础-内存管理_ancinsdn的博客-程序员宝宝

好记性不如烂笔头。。。 工作这么多年还是要有点沉淀。。。

一 JVM内存范围


1、方法区(Method Area): 对于我们使用HotSpot虚拟机的程序员来说,方法区即平时我们所说的永久代(Perm Gen),它用于存储已被虚拟机加载的类信息,常量,以及静态变量等数据。虽然java虚拟机规范将方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做非堆(No-Heap),目的是为了与堆进行区分,HotSpot虚拟机设计团队只是为了让方法区与java堆统一使用分代GC机制,才将它命名为永久代,与新生代(New Gen)老年代(Tenured Gen)使用同一套内存管理代码。运行时常量池(Runtime Constant Pool)属于方法区的一部分。

2、虚拟机栈(VM stack):虚拟机栈描述的是Java方法执行的内存模型,每个方法在执行同时会创建一个栈帧(Stack Frame),用于存储局部变量表(存放编译可知的基本数据类型,对象引用和returnAddress),操作数栈,动态链接,方法出口等信息。每个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中的入栈与出栈的过程。

3、本地方法栈(Native stack):与虚拟机栈类似,区别就是虚拟机栈执行的是java方法(字节码),而本地方法栈执行的是Native方法。

4、堆(Heap):堆是虚拟机所管理的内存最大的一块,这块内存唯一的作用就是存放对象实例。几乎所有的对象实例以及数组都要在堆上分配内存。同时,我们平时所说的垃圾回收也大部分(堆外还有方法区与直接内存)集中在堆上,这是垃圾收集器管理的最主要的区域,后面会对堆这块进行详细介绍。

5、程序计数器:可以当作当前线程的执行的字节码的行号指示器,分支、循环、跳转、异常处理等基础功能都需要依赖程序计数器来指定到下一条要执行的字节码指令。

6、直接内存(Direct Memory):也就是狭义上的堆外内存,jdk1.4后引入了NIO包,为了提高I/O性能,该包下面提供了一个使用Native方法直接分配堆外内存的类-DirectByteBuffer,数据存储在直接内存,堆中的DirectByteBuffer对象作为该块内存的引用。该部分内存的分配不受java堆大小的限制,只会受本机总内存以及处理器寻址空间的限制。JDK5.0之后,代码中能直接操作本地内存的方式有2种:使用未公开的Unsafe和NIO包下ByteBuffer。


二 堆内存分配


1、对象优先在Eden分配:大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够的空间进行分配时,虚拟机将会进行一次Minor GC

2、大对象直接进入老年代:这样做的目的是为了防止在Eden区以及两个survivor区发生大量的内存的复制。虚拟机提供了一个参数-XX:PretenureSizeThreshold参数用来设置这个大对象的值。

3、长期存活的对象将进入老年代虚拟机给每个对象分配了一个对象年龄(Age)计数器,如果对象在Eden区出生并且经过第一次Minor GC后仍然存活,并且能够被Survivor区容纳的话,将会被移到Survivor空间中,并且年龄设为1.对象在Survivor空间中每‘熬过’一次Minor GC,年龄就增加1岁。当他年龄增加到一定程度(默认15)时,就会晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过-XX:MaxTenuringThreshold设置。


Minor GC的过程。下面逐步说明GC过程:

a、新生代GC时,先将Eden区的存活的对象复制到To Survivor,年龄置为1,清空Eden区;
     b、然后回收From Survivor,首先将From Survivor中存活的对象年龄加1,然后判断年龄是否达到进入老年代的准入条件(默认15岁,可通过-XX:MaxTenuringThreshold设置),如果达到准入条件则进入老年代,否则进入To Survivor;清空From Survivor。
    c、交换From Survivor 与To Survivor,保证每次GC前To Survivor空间都是空的。

    d、下次GC时循环上述过程。

4、Survivor空间中相同年龄的所有对象大小的总和大于Survivor空间的一半时,年龄等于或者大于该年龄的对象就可以直接进入老年代中,而无需等到MaxTenuringThreshold这个阈值。

5、Full GC的发生条件:在发生Minor GC之前,虚拟机会去检查老年代中最大可用连续内存空间是否大于新生代所有对象总空间,如果这个条件成立,那么可以确保这次minor GC是安全的,如果不成立,则虚拟机回去查看HandlePromotionFailure设置的值是否允许担保失败。如果允许,则虚拟机会继续检查老年代中最大可用连续内存空间大小是否大于历次晋升到老年代对象的平均大小,如果大于,则会尝试进行一次Minor GC,即便这次Minor GC是有风险的。如果小于,或者HandlePromotionFailure设置不允许冒险,那这时要改为进行一次Full GC

注意:在JDK 6 update 24后,HandlePromotionFailure不再会影响虚拟机分配担保策略,规则变为只要老年代连续可用内存大小大于新生代所有对象总大小或者历次晋升老年代对象的平均大小就进行Minor GC,否则进行Full GC。

下面通过代码验证一下内存分配策略。

下面通过代码验证一下内存分配策略。

第一步:分配堆内各区域内存大小:堆大小20M,其中新生代10M,老年代10M;新生代中Eden与Survivor比例采用默认的8:1,即Eden区8M,两个Survivor区分别1M。此外,打印出GC信息。配置如下:

-verbose:gc  -XX:+PrintGCDetails  -Xms20M -Xmx20M  -Xmn10M  -XX:SurvivorRatio= 8

第二步:执行如下代码

/**
  * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
 
  * @author huolie
  * @version $Id: TestGC.java, v 0.1 2016年11月10日 下午8:35:42 huolie Exp $
  */
public  class  TestGC {
     private  final  static  int  _1MB =  1024  1024 ;
     /**
     
      * @param args
      */
     public  static  void  main(String[] args) {
         byte [] bt1, bt2, bt3, bt4;
         bt1 =  new  byte [ 2  * _1MB];
         bt2 =  new  byte [ 2  * _1MB];
         bt3 =  new  byte [ 2  * _1MB];
         bt4 =  new  byte [ 0  * _1MB];
     }
}

a、验证对象优先在Eden分配。

b、验证Eden区空间不足时进行Minor GC。修改上面代码,将bt4=new byte[0 * _1MB];修改为bt4=new byte[1 * _1MB]; 运行代码

c、验证大对象直接进入老年代。修改代码,将bt4=new byte[0 * _1MB];修改为bt4=new byte[4 * _1MB];同时启动参数中增加-XX:PretenureSizeThreshold=4M,运行代码

d、验证Full GC的发生。修改代码,增加bt5=new byte[7 * _1MB];保持-XX:PretenureSizeThreshold=4M。运行代码

三、关于启动参数的配置说明

1、-Xms, -XX:MinHeapFreeRatio,-Xmx,-XX:MaxHeapFreeRatio 这四个参数用来控制堆内存(新生代与老年代)整体大小,-Xms用于设置初始堆大小,空余堆内存小于MinHeapFreeRatio(默认40%)时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于MaxHeapFreeRatio(默认70%)时,JVM会减少堆直到 -Xms的最小限制。

2、-Xmn,-XX:NewRatio,-XX:SurvivorRatio 三个参数用来控制新生代(包括Eden与Survivor)、老年代的内存分配。其中-Xmn用来控制新生代大小,-XX:NewRatio用来控制新生代与老年代的比例,-XX:SurvivorRatio 用来控制新生代中Eden区与Survivor区的比例,默认为8:1:1。当-Xmn与-XX:NewRatio两个同时配置时,-Xmn优先级高。通过-Xmn与-XX:SurvivorRatio 或者-XX:NewRatio,-XX:SurvivorRatio 就可以对新生代内存以及老年代内存进行划分。

3、-XX:PermSize,-XX:MaxPermSize 用于设置永久代(Prem Gen)的大小。








版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ancinsdn/article/details/56279347

智能推荐

新华三MSG网关无线MAC白名单过滤_Try to live的博客-程序员宝宝_h3c mac地址过滤

H3C MSG360系列集成路由,AC多功能一体的网关设备通过web页面可以设置较多的功能,但有些功能无法通过web页面来设置,只能通过命令行的模式来设置前段时间有个客户提了个场景需求,设置两个SSID,一个为内部使用的无线,通过MAC白名单过滤,非白名单的终端不能上网,另一个为访客网络,需通过客户提供的账户密码登录后才能上网,通过web页面无法实现(web界面设置的白名单全局生效),只能通过命令行的模式进行设置,我把当时做的过程分享下1,首先登入web界面设置基本信息,无线信息2,通过consol

Android中Toast的简单使用_生活不允许普通人内向的博客-程序员宝宝_安卓toast

1. 概述Toast 是一个 View 视图,快速的为用户显示少量的信息。 Toast 在应用程序上浮动显示信息给用户,它永远不会获得焦点,不影响用户的输入等操作,主要用于 一些帮助 / 提示。Toast 最常见的创建方式是使用静态方法 Toast.makeText()。2. Toast.makeText()Toast.makeText()有3个参数:(1)第一个参数:当前的...

深入浅出 Linux Vsftpd创建多虚拟用户教程_u010154380的博客-程序员宝宝

深入浅出 Linux Vsftpd创建多虚拟用户教程Vsftpd 是一款轻量级并有着安全与简易等特性的FTP服务器程序,破受欢迎。在 Linux 中一旦配置好 Vsftpd 环境就可以一劳永逸,任意的迁移到类似的服务器之上,因此我们对配置过程做个系统的了解也是有必要的。本文的任务是创建两个虚拟账户,第一个账户(bugxm_admin)拥有可读写指定目录文件、不可登陆系统权限,第二个(b

报错java.lang.ClassNotFoundException: org.apache.jsp.WEB_002dINF.page_伶仃小镇的博客-程序员宝宝

报错:org.apache.jasper.JasperException: java.lang.ClassNotFoundException: org.apache.jsp.WEB_002dINF.pages.user_005faccuses_jsp  无效!方法一: 在maven的pom.xml文件中加入如下两个dependency,问题解决,并且不需要加入上述的JSTL的jar包<dep...

GsonFormat的安装及使用_waterair_li的博客-程序员宝宝

GsonFormat的安装及使用一、 安装方法一:1.Android studio ->> Prefernce ->> Plugins ->> Browse repositores… ->>搜索GsonFormat2.安装插件,重启android studio方法二:1.下载GsonFormat.jar2.Android studio ...

Centos7搭建Samba服务器_Z.Bowen的博客-程序员宝宝

1.准备工作关闭防火墙关闭selinux systemctl stop firewalld.service setenforce 0 && getenforce && \cp /etc/selinux/config{,.ori} &am

随便推点

LeetCode300题计划——5.最长回文子串_MY_NEW_LIFE的博客-程序员宝宝

题目: 给你一个字符串 s,找到 s 中最长的回文子串。package ListNode;public class longestPalindrome { public static void main(String[] args) { // TODO Auto-generated method stub }}class Solution5 { public String longestPalindrome(String s) { int len = s..

机器学习自动化 要学习什么_从电视节目“先生”中学习自动化网络安全。 机器人'_weixin_26722031的博客-程序员宝宝

机器学习自动化 要学习什么 电视可以教给您有关IT / OT融合的知识 (Here’s What Television Can Teach You About IT/OT Convergence)As our world becomes more and more interconnected, automation professionals are realizing that cybers...

石子合并——最经典的dp问题_少年白马的博客-程序员宝宝

石子合并三大题型任意两堆石子合并,直接手写一个小根堆,每次取前面两个相加,得到的值继续放入优先队列中,直到里面只有一个元素就输出只能合并相邻两堆石子,这就类似于矩阵连乘(传送门),不过还是有一些差别在2的基础上,这些石子形成一个环形,这又是一种新的题型今天记录的是第二种——区间dp题目描述在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位...

k-近邻算法(KNN)_勤奋的小学生的博客-程序员宝宝

简介k-近邻算法就是采用测量不同特征值之间的距离方法进行分类。工作原理:存在一个样本数据集合,就是训练样本集,并且每个数据都有标签。即每一个数据与所属分类的对应关系。所以KNN是一个监督式学习。然后,输入没有标签的数据,将新数据的每个特征与训练样本集中数据对应的特征进行比较,最后算法提取训练样本集中特征最相似数据的分类标签。通常情况下,我们选择前k个最相似的数据,而选择k个最相似数据中...

nyoj 144 小珂的苦恼_ygqwan的博客-程序员宝宝

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=144本题主要用到的是扩展欧几里德定理: 对于与不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数那么存在唯一的整数 x,y.使得 gcd(a,b)=ax+by; #includeint a,b,n,t;int gy(){ int c=1;

HDU 4430 - Yukari's Birthday_Freenm的博客-程序员宝宝

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5505    Accepted Submission(s): 1320Problem DescriptionToday is Yukari's n-th b

推荐文章

热门文章

相关标签