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. easyui 分页实现

    1.用datagrid 做分页显示, 依据API样例,最终解决.废话不说,datagrid分页 有一个附加的分页控件 通过在datagrid中设置pagination:true 就会显示分页 当请求是 ...

  2. atitit。浏览器缓存机制 and 微信浏览器防止缓存的设计 attilax 总结

    atitit.浏览器缓存机制 and 微信浏览器防止缓存的设计 attilax 总结 1. 缓存的一些机制 1 1.1. http 304 1 1.2. 浏览器刷新的处理机制 1 1.3. Expir ...

  3. Visual Studio 2012 Ultimate 上安装 Python 开发插件 PTVS

    1.我的环境 操作系统:32位 Win7 旗舰版 Service Pack 1 VS版本:Microsoft Visual Studio Ultimate 2012 版本 11.0.50727.1 R ...

  4. Chapter 7. Dependency Management Basics 依赖管理基础

    This chapter introduces some of the basics of dependency management in Gradle. 7.1. What is dependen ...

  5. -bash: ulimit: open files: cannot modify limit: Operation not permitted

    普通用户登录系统报错,提示: -bash: ulimit: open files: cannot modify limit: Operation not permitted. 处理方法: #vi /e ...

  6. activeMQ总结

    队列模式和发布订阅模式的区别 topic只有所有订阅者都消费了,这个消息才会消失.只要有一个订阅者没有消费(持久化模式),这个消息就会存在.订阅者下线然后上线也会读取到这个消息.而且队列的话,消费能力 ...

  7. parent.location.href和location.href区别

    parent.location.href='ind.php'parent用于框架结构,需要全网页转向如果你的网页是左右框架,那么,直接把当前页面全部转到ind.php中 location.href=' ...

  8. Cacti安装教程

    CentOS 6.0架设流量监控及集中日志系统 第一章.cacti的安装 1. 系统的基本设置2. 设置主机名3. [root@localhost ~]# vi /etc/sysconfig/netw ...

  9. mysql window下tmpdir空间耗尽

    修改my.ini或my-default.ini文件[mysqld]下方配置 tmpdir = D:/tmp

  10. zepto源码研究 - zepto.js-4(常用的工具)

    $.each: /** * 以集合每一个元素作为上下文,来执行回调函数 * @param elements * @param callback * @returns {*} */ $.each = f ...