JVM的内存结构,JVM的回收机制
内存作为系统中重要的资源,对于系统稳定运行和高效运行起到了关键的作用,Java和C之类的语言不同,不需要开发人员来分配内存和回收内存,而是由JVM来管理对象内存的分配以及对象内存的回收(又称为垃圾回收、GC),这对于开发人员来说确实大大降低了编写程序的难度,但带来的一个副作用就是,当系统运行过程中出现JVM抛出的内存异常(例如OutOfMemoryError)的时候,很难知道原因是什么,另外一方面,要编写高性能的程序,通常需要借助内存来提升性能,因此如
何才能合理的使用内存以及让JVM合理的进行内存的回收是必须掌握的,本节将主要分析一下JVM的内存结构。
其实对于我们一般理解的计算机内存,它算是CPU与计算机打交道最频繁的区域,所有数据都是先经过硬盘至内存,然后由CPU再从内存中获取数据进行处理,又将数据保存到内存,通过分页或分片技术将内存中的数据再flush至硬盘。那JVM的内存结构到底是如何呢?JVM做为一个运行在操作系统上,但又独立于os运行的平台,它的内存至少应该包括象寄存器、堆栈等区域。
JVM在运行时将数据划分为了6个区域来存储,而不仅仅是大家熟知的Heap区域,这6个区域图示如下:
JVM在运行时将数据划分为了6个区域来存储,而不仅仅是大家熟知的Heap区域
一 PC Register(PC寄存器)
PC寄存器是一块很小的内存区域,主要作用是记录当前线程所执行的字节码的行号。字节码解释器工作时就是通过改变当前线程的程序计数器选取下一条字节码指令来工作的。任何分支,循环,方法调用,判断,异常处理,线程等待以及恢复线程,递归等等都是通过这个计数器来完成的。
由于Java多线程是通过交替线程轮流切换并分配处理器时间的方式来实现的,在任何一个确定的时间里,在处理器的一个内核只会执行一条线程中的指令。
因此为了线程等待结束需要恢复到正确的位置执行,每条线程都会有一个独立的程序计数器来记录当前指令的行号。计数器之间相互独立互不影响,我们称这块内存为“线程私有”的内存。
如果所调用的方法为native的,则PC寄存器中不存储任何信息。
二 JVM栈
JVM栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放的为当前线程中局部基本类型的变量(java中定义的八种基本类型:boolean、char、byte、short、int、long、float、double)、部分的返回结果以及Stack Frame,
非基本类型的对象在JVM栈上仅存放一个指向堆上的地址,因此Java中基本类型的变量是值传递,而非基本类型的变量是引用传递,Sun JDK的实现中JVM栈的空间是在物理内存上分配的,而不是从堆上分配。
由于JVM栈是线程私有的,因此其在内存分配上非常高效,并且当线程运行完毕后,这些内存也就被自动回收。
当JVM栈的空间不足时,会抛出StackOverflowError的错误,在Sun JDK中可以通过-Xss来指定栈的大小
三 堆(Heap)
Heap是大家最为熟悉的区域,它是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,
Heap中的对象的内存需要等待GC进行回收,Heap在32位的操作系统上最大为2G,在64位的操作系统上则没有限制,
其大小通过-Xms和-Xmx来控制,-Xms为JVM启动时申请的最小Heap内存,默认为物理内存的1/64但小于1G,-Xmx为JVM可申请的最大Heap内存,默认为物理内存的1/4,默认当空余堆内存小于40%时,JVM会增大Heap的大小到-Xmx指定的大小
,可通过-XX:MinHeapFreeRatio=来指定这个比例,当空余堆内存大于70%时,JVM会将Heap的大小往-Xms指定的大小调整,可通过-XX:MaxHeapFreeRatio=来指定这个比例,
但对于运行系统而言,为了避免频繁的Heap Size的大小,通常都会将-Xms和-Xmx的值设成一样,因此这两个用于调整比例的参数通常是没用的。其实jvm中对于堆内存的分配、使用、管理、收集等有更为精巧的设计,具体可以在JVM堆内存分析中进行详细介绍。
当堆中需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
四 方法区域(MethodArea)
方法区域存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,
当开发人员在程序中通过Class对象中的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域,可见方法区域的重要性
。同样,方法区域也是全局共享的,它在虚拟机启动时在一定的条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
在Sun JDK中这块区域对应的为PermanetGeneration,又称为持久代,默认为64M,可通过-XX:PermSize以及-XX:MaxPermSize来指定其大小。
五 运行时常量池(RuntimeConstant Pool)
类似C中的符号表,存放的为类中的固定的常量信息、方法和Field的引用信息等,其空间从方法区域中分配。类或接口的常量池在该类的class文件被java虚拟机成功装载时分配。
六 本地方法堆栈(NativeMethod Stacks)
JVM采用本地方法堆栈来支持native方法的执行,此区域用于存储每个native方法调用的状态
GC回收机制
1、新生代:在新生代里的每一个对象,都会有一个年龄,当这些对象的年龄到达一定程度时(年龄就是熬过的GC次数,每次GC如果对象存活下来,则年龄加1),则会被转到年老代,而这个转入年老代的年龄值,一般在JVM中是可以设置的。
2、年老代:在新生代存活对象占用的内存超过10%时,则多余的对象会放入年老代。这种时候,年老代就是新生代的“备用仓库”。
3、永久代:在我们常用的hotspot虚拟机(JDK默认的JVM)中,方法区也被亲切的称为永久代。
回收的时机
JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代。因此GC按照回收的区域又分了两种类型,一种是普通GC(minor GC),一种是全局GC(major GC or Full GC),它们所针对的区域如下。
普通GC(minor GC):只针对新生代区域的GC。
全局GC(major GC or Full GC):针对年老代的GC,偶尔伴随对新生代的GC以及对永久代的GC。
由于年老代与永久代相对来说GC效果不好,而且二者的内存使用增长速度也慢,因此一般情况下,需要经过好几次普通GC,才会触发一次全局GC。
JVM的内存结构,JVM的回收机制的更多相关文章
- 巩固java(二)----JVM堆内存结构及垃圾回收机制
前言: 我们在运行程序时,有时会碰到内存溢出(OutOfMemoryError)的问题,为了解决这种问题,我们有必要了解JVM的内存结构和垃圾回收机制. 正文: 1.JVM堆内存结构 ...
- JVM 垃圾回收机制和常见算法和 JVM 的内存结构和内存分配(面试题)
一.JVM 垃圾回收机制和常见算法 Sun 公司只定义了垃圾回收机制规则而不局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同.GC(Garbage Collector)在回收对象前首先必 ...
- JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)
转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...
- JVM内存分配与垃圾回收机制管理
项目上线,性能优化有个重要组成就是jvm内存分配和垃圾回收机制的管理配置. 网上随便能搜到相关的具体步骤,以及内存中各种参数对应的意义,不再赘述. 干货就是直接抛出遇到的问题,以及如何解决的,再说说待 ...
- JVM内存管理和垃圾回收机制介绍
http://backend.blog.163.com/blog/static/20229412620128233285220/ 内存管理和垃圾回收机制是JVM最核心的两个组成部分,对其内部实 ...
- 【高频Java面试题】简单说说JVM堆的内存结构和GC回收流程
目录 前言 JVM堆内存结构简述 JVM堆内存结构图 堆初体验 结构详情 新生代 老年代 永久代/元空间 GC回收流程 GC回收流程图 GC回收详细流程 查看JDK自带可视化堆空间图 总结 前言 我们 ...
- JVM:内存结构
JVM:内存结构 说明:这是看了 bilibili 上 黑马程序员 的课程 JVM完整教程 后做的笔记 内容 程序计数器 虚拟机栈 本地方法栈 堆 方法区 直接内存 1. 程序计数器 1.1 定义 P ...
- JVM之内存结构详解
对于开发人员来说,如果不了解Java的JVM,那真的是很难写得一手好代码,很难查得一手好bug.同时,JVM也是面试环节的中重灾区.今天开始,<JVM详解>系列开启,带大家深入了解JVM相 ...
- JVM的内存结构以及性能调优
JVM的内存结构以及性能调优 发布时间: 2017-11-22 阅读数: 16675 JVM的内存结构以及性能调优1:JVM的结构主要包括三部分,堆,栈,非堆内存(方法区,驻留字符串)堆上面存储的是引 ...
随机推荐
- 重构改善既有代码设计--重构手法10:Move Method (搬移函数)
你的程序中,有个函数与其所驻类之外的另一个类进行更多的交流:调用后者,或被后者调用.在该函数最常用引用的类中建立一个有着类似行为的新函数.将旧函数编程一个单纯的委托函数,或是将旧函数完全移除. 动机: ...
- Isomorphic JavaScript: The Future of Web Apps(译)
Isomorp ...
- 引用类型 ( 对象定义 )——RegExp 类型
var expression = /pattern/flags; 以上为创建正则表达式格式,斜线包围的为正则表达式,flags 有三个值可以选择 本文地址:http://www.cnblogs.com ...
- ogg数据初始化历程记录
之前,源端数据表结构发生改变,不知道前面的同事是怎么搞得(生成的数据定义文件不对,还是没有把进程启动),造成进程停止20天,然后重启复制进程,对比源端和目标端数据有差异(总共差10000多条数据),问 ...
- linux 下 genymotion 模拟器不能安装app
提示: "应用未安装" 解决方法: 下载: Genymotion-ARM-Translation_v1.1.zip 进入genymotion 的tools用adb传进去: ./ad ...
- 用户空间与内核空间数据交换的方式(9)------netlink【转】
转自:http://www.cnblogs.com/hoys/archive/2011/04/10/2011722.html Netlink 是一种特殊的 socket,它是 Linux 所特有的,类 ...
- juery下拉刷新,div加载更多元素并添加点击事件(二)
buffer.append("<div class='col-xs-3 "+companyId+"' style='padding-left: 10px; padd ...
- 21.Merge Two Sorted Lists---《剑指offer》面试17
题目链接:https://leetcode.com/problems/merge-two-sorted-lists/description/ 题目大意: 给出两个升序链表,将它们归并成一个链表,若有重 ...
- ubuntu遇到的 the system is runing low-graphics mode 问题
不知道修改了什么,然后开机显示the system is runing low-graphics mode 看过博客使用如下方法成功进入系统,但是显示分辨率很低,显示 built-in display ...
- 2017百度春招<不等式排列>
题目: 度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 '>' 和 '<' )使其成为一个合法的不等式数列.但是现在度度熊 ...