JAVA能够实现跨平台的一个根本原因,是定义了class文件的格式标准,凡是实现该标准的JVM都能够加载并解释该class文件,据此也可以知道,为啥Java语言的执行速度比C/C++语言执行的速度要慢了,当然原因肯定不止这一个,如在JVM中没有数据寄存器,指令集使用的是栈来保存中间数据…等,尽管Java的贡献者们为执行速度的提高想了各种办法,如JIT、动态编译器等,以下是Leetcode中一道题目用不同的语言实现时的执行性能对比图…

以下是JVM的一个基本架构图,在这个基本架构图中,栈有两部份,Java线程栈以及本地方法栈,栈的概念与C/C++程序基本上都是一个概念,里面存放的都是栈帧,一个栈帧代表的就是一个函数的调用,在栈帧里面存放了函数的形参,函数的局部变量, 返回地址等,但是与C/C++的一个重要区别是,C/C++里面有传值以及传址的区别,当传的是一个对象时( 结构体也可以当成对象,其实就是对象~,只不过里面的方法默认都是public的,不信你可以试试,在结构体中加一个函数,编译器也不会报错,程序依旧运行~~~),会将对象复到到栈中,而Java中只有基本类型才是传值的,其他类型传的都是引用,什么是引用,学过C/C++的就把引用当作指针理解吧~~~,在这个基本架构图中,可以看出JVM还定义了一个本地方法栈,本地方法栈是为Java调用本地方法【这些本地方法是由其他语言编写的】服务的

上面的图中看到的是JVM中栈有两个,但是堆只有一个,每一个线程都有自已的线程栈【线程栈的大小可以通过设置JVM的-xss参数进行配置,32位系统下,一般默认的大小是512K】,线程栈里面的数据属于该线程私有,但是所有的线程都共享一个堆空间,堆中存放的是对象数据,什么是对象数据,排除法,排除基本类型以及引用类型以外的数据都将放在堆空间中,下面来具体分析一下堆空间…

在JVM中堆空间划分如下图所示

上图中,刻画了Java程序运行时的堆空间,可以简述成如下2条

1.JVM中堆空间可以分成三个大区,新生代、老年代、永久代

2.新生代可以划分为三个区,Eden区,两个幸存区

在JVM运行时,可以通过配置以下参数改变整个JVM堆的配置比例

1.JVM运行时堆的大小

  -Xms堆的最小值

  -Xmx堆空间的最大值

2.新生代堆空间大小调整

  -XX:NewSize新生代的最小值

  -XX:MaxNewSize新生代的最大值

  -XX:NewRatio设置新生代与老年代在堆空间的大小

  -XX:SurvivorRatio新生代中Eden所占区域的大小

3.永久代大小调整

  -XX:MaxPermSize

4.其他

   -XX:MaxTenuringThreshold,设置将新生代对象转到老年代时需要经过多少次垃圾回收,但是仍然没有被回收

在上面的配置中,老年代所占空间的大小是由-XX:SurvivorRatio这个参数进行配置的,看完了上面的JVM堆空间分配图,可能会奇怪,为啥新生代空间要划分为三个区Eden及两个Survivor区?有何用意?为什么要这么分?要理解这个问题,就得理解一下JVM的垃圾收集机制(复制算法也叫copy算法),步骤如下:

复制(Copying)算法

将内存平均分成A、B两块,算法过程:

1. 新生对象被分配到A块中未使用的内存当中。当A块的内存用完了, 把A块的存活对象对象复制到B块。
2. 清理A块所有对象。
3. 新生对象被分配的B块中未使用的内存当中。当B块的内存用完了, 把B块的存活对象对象复制到A块。
4. 清理B块所有对象。
5. goto 1。

优点:简单高效。缺点:内存代价高,有效内存为占用内存的一半。

图解说明如下所示:(图中后观是一个循环过程)

对复制算法进一步优化:使用Eden/S0/S1三个分区

平均分成A/B块太浪费内存,采用Eden/S0/S1三个区更合理,空间比例为Eden:S0:S1==8:1:1,有效内存(即可分配新生对象的内存)是总内存的9/10。

算法过程:

1. Eden+S0可分配新生对象;
2. 对Eden+S0进行垃圾收集,存活对象复制到S1。清理Eden+S0。一次新生代GC结束。
3. Eden+S1可分配新生对象;
4. 对Eden+S1进行垃圾收集,存活对象复制到S0。清理Eden+S1。二次新生代GC结束。
5. goto 1。

默认Eden:S0:S1=8:1:1,因此,新生代中可以使用的内存空间大小占用新生代的9/10,那么有人就会问,为什么不直接分成两个区,一个区占9/10,另一个区占1/10,这样做的原因大概有以下几种

1.S0与S1的区间明显较小,有效新生代空间为Eden+S0/S1,因此有效空间就大,增加了内存使用率
2.有利于对象代的计算,当一个对象在S0/S1中达到设置的XX:MaxTenuringThreshold值后,会将其分到老年代中,设想一下,如果没有S0/S1,直接分成两个区,该如何计算对象经过了多少次GC还没被释放,你可能会说,在对象里加一个计数器记录经过的GC次数,或者存在一张映射表记录对象和GC次数的关系,是的,可以,但是这样的话,会扫描整个新生代中的对象, 有了S0/S1我们就可以只扫描S0/S1区了~~~

GC实例分析,下次再分析~

JVM内存堆布局图解分析的更多相关文章

  1. [转]JVM内存堆布局图解分析

    JAVA能够实现跨平台的一个根本原因,是定义了class文件的格式标准,凡是实现该标准的JVM都能够加载并解释该class文件,据此也可以知道,为啥Java语言的执行速度比C/C++语言执行的速度要慢 ...

  2. JVM深入:JVM内存堆布局图解分析(转)

    转载自:https://www.cnblogs.com/SaraMoring/p/5713732.html 原文:http://www.codeceo.com/article/jvm-memory-s ...

  3. JVM 内存 (堆(heap)、栈(stack)和方法区(method) )

    JVM 内存初学 (堆(heap).栈(stack)和方法区(method) ) 堆区: 1.存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的目的是得到操作指令)2.jv ...

  4. JVM内存—堆(heap)栈(stack)方法区(method) (转)

    JAVA的JVM的内存可分为3个区:堆(heap).栈(stack)和方法区(method) 堆区:1.存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的目的是得到操作指令 ...

  5. JVM(二)JVM内存布局

    这几天我再次阅读了<深入理解Java虚拟机>之第二章"Java内存区域与内存溢出异常",同时也参考了一些网上的资料,现在把自己的一些认识和体会记录一下.  (本文为博主 ...

  6. jvm系列(二):JVM内存结构

    JVM内存结构 所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能 ...

  7. jvm系列二、JVM内存结构

    原文链接:http://www.cnblogs.com/ityouknow/p/5610232.html 所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemory ...

  8. JVM内存结构(转)

    所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问 ...

  9. Java虚拟机(一):JVM内存结构

    所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问 ...

随机推荐

  1. boost 特点

    功能强大 跨平台 开源 免费 构造精巧 C++扩展库

  2. shell 判断文件、目录是否存在

    shell判断文件是否存在   1. shell判断文件,目录是否存在或者具有权限 2. #!/bin/sh 3. 4. myPath="/var/log/httpd/" 5. m ...

  3. EF 已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭

    在以下代码中,当第二次foreach时会抛出该异常,原因是:由于Entity在读取数据的时候使用的是DbDataReader进行读取,当作为IEnumuerable<T>对象MoveNex ...

  4. hdu 1870

    水题.... AC代码: #include <iostream> #include <queue> using namespace std; int main() { char ...

  5. elasticsearch中的概念简述

    Near Realtime(NRT) Elasticsearch接近实时.从为一个文档建立索引到可被搜索,正常情况下有1秒延迟. Cluster 一个集群有一个唯一的名字,默认是"elast ...

  6. (转)SQL流程控制语句学习(二):begin…end if…else case

    1.begin…end 语法: begin {sql语句或语句块} end 注意:begin 和end要成对使用 2.if…else 语法: if  布尔表达式 {sql语句或语句块} else  布 ...

  7. Oracle 11g随Redhat 5系统自动启动与关闭的设置方法

    最近,ORACLE系统基本调试通过,是时候设置ORACLE随RHEL自动启动与关闭服务的时候了,之所以把这个任务放在最后来做,是因为我觉得这个应该不会很难,但真正实施起来,还是遇到了个不小的障碍:写好 ...

  8. 监听UITabBarItem来拦截是否要跳转

    情景是这样的: 我需要在用户点击"我的"的时候, 判断是否已经登录, 如果没有, 就不进入该界面, 而是跳转到用户登录界面, 所以这里我需要进行UITabBarItem点击事件的拦 ...

  9. Ps 美白磨皮【1】

      方法一:去色加图层模式法 打开需要编辑的图片,按Ctrl+J复制新的图层1. 点击菜单栏“图像”-“调整”-“去色”,如下图所示. 将图层面板的混合模式更改为“滤色”,如下图4所示. 最后的显示效 ...

  10. CentOS 7 之Shell学习笔记

    脚本是个永恒的话题,以前Dos下面也有Shell编程这一说的,比如说BAT文件有人写的好的话,也是瞬间速度变高大上.Linux下面这个应该更占比重了.我看到园子里有位园友做了一个Linux Shell ...