Jvm相关知识点

Jvm组成部分

1. PC寄存器/程序计数器

一块小的内存空间,作用可以看做是当前线程所执行的字节码的行号指示器。分支,循环,跳转,异常处理,线程恢复等基础功能都依赖计数器完成。在任何一个时刻,一个处理器只会执行一条线程中的指令,因此,为了线程切换后能恢复到正确的执行位置,每条线程需要一个独立的程序计数器(私有内存)。Java方法的计数器记录正在执行的虚拟机字节码指令的地址,Native方法的计数器为空。计数器不存在OutofMemoryError.

2. Jvm栈

Jvm栈也是线程私有的,生命周期与线程相同。Jvm栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会创建一个栈帧(stackframe)用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在Jvm栈从入栈到出栈的过程。局部变量表存放了基本数据类型(boolean,byte,char,short,int,float,long,double),对象引用(指向对象地址的指针)和returnAddress(指向一条字节码指令的地址)。在方法运行期间不会改变局部变量表大小。

3. 本地方法栈

本地方法栈作用与Jvm栈作用类似,区别不过是Jvm栈执行的是Java方法,本地方法栈执行的是Native方法。

4. Jvm堆

Jvm堆是Jvm内存最大的一块,被所有线程所共享。Jvm堆在Jvm启动时创建,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。Jvm堆是垃圾收集器(GC)管理的主要区域。Jvm堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。因为堆是Jvm中所有线程所共享的,因此在其上进行对象内存分配均需要进行加锁,这也导致了new对象的开销是比较大的。Sun Hotspot Jvm为了提升对象内存分配的效率,对于所创建的线程都会分配一块独立的空间TLAB(Thread Local Allocation Buffer),其大小由Jvm根据运行的情况计算而得,在TLAB上分配对象不用加锁,因此Jvm给线程分配对象的内存时会尽可能的在TLAB上分配,如果对象过大,则仍需在堆空间分配。TLAB仅作用于Eden Space。

5. 方法区

与Jvm堆一样,方法区是各个线程共享的区域,它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。方法区也可以叫永生代,但是Hotspot准备放弃永生代,使用Native Memory来实现方法区。相对而言,GC在这个区域比较少的出现,这个区域内回收目标主要是常量池和对类型的卸载。

6. 运行时常量池

运行时常量池是方法区的一部分,这里存放的是类中的固定的常量信息,方法和Field的引用信息。

Jvm垃圾回收机制

触发GC的条件:

1)GC在优先级最低的线程中进行,一般在应用程序空闲,即没有应用程序在运行时,被调用。

2)例外: 当Jvm堆内存不足时,GC会被调用。当应用线程正在运行,并且在运行过程中创建对象,若这时内存不足,Jvm会强制调用GC。若一次GC之后仍不能满足内存分配,Jvm会再次进行两次GC,若仍不能满足,Jvm报OutofMemoryError,Java应用停止。

GC的Generation算法(分代收集算法)

分代收集算法是大部分Jvm的垃圾收集器采用的算法。他的核心思想是根据对象存活的生命周期,将内存划分为若干个不同的区域。一般情况下将堆分为老年代新生代,方法区为永生代(新版本将永生代废弃,引入元空间的概念,永生代使用Jvm内存儿元空间直接使用物理内存)。新生代分为Eden区和Survivor区(Survivor from和Survivor to),大小比例默认为8:1:1.新产生的对象优先进入Eden区,当Eden区满了之后再使用Survivor from,当Survivor from也满了之后,就进行Minor GC(新生代GC),将Eden和Survivor from中存活的对象使用Copying算法复制进入Survivor to,原来的Survivor to就成了新的Survivor from,Copying算法在复制之后清空Eden和Survivor from,原来的Survivor from就成了新的Survivor to。复制的时候,如果Survivor to无法容纳全部存活的对象,则根据老年代的分配担保,将对象复制进入老年代,如果老年代也无法容纳,则进行Full GC(老年代GC或者称为Major GC)。老年代的特点就是每次垃圾收集时,只有少量对象需要被回收,而新生代的特点是每次都要回收大量的对象,因此可以根据不同代的特点采取合理的收集算法。程序中主动调用System.gc()强制执行的GC为Full GC。
Jvm对新生代采用Copying算法,因为新生代每次GC都要回收大部分对象,需要复制的操作次数较少;
老年代的特点是每次GC只回收少量对象,一般使用Mark-Compact算法;

1)大对象直接进入老年代,Jvm有个参数配置,大于这个值直接进入老年代,避免Eden和Survivor区之间发生大量的对象复制操作。

2)长期存活的对象进入老年代,Jvm给每个对象定义一个对象年龄计数器,如果对象在Eden出生,经历一次Minor GC之后仍存活,将其移入Survivor区并且年龄+1.每经过一次GC年龄+1,当年龄到达15(Jvm参数,默认为15),移入老年代。

3)但是Jvm不是永远要求年龄必须达到最大年龄才可以晋升老年代,如果Survivor空间中相同年龄(如年龄X)的所有对象大小的总和大于Survivor的一半时,年龄大于等于X的所有对象直接进入老年代。

简单的三个收集算法

1)标记清除算法:

分标记,清除两个阶段。首先标记所需要回收的对象,在标记完成之后统一回收所有被标记的对象。不足:一个效率问题,标记和清除的效率都不高;一个空间问题,标记清除之后产生了大量不连续的内存碎片,碎片太多导致需要分配大对象时无法找到足够的连续内存而不得不再触发一次GC。

2)复制算法Copying:

为了解决效率问题,复制算法将可用的内存分为两部分,每次只使用其中一块,当一块内存用完了,将还存活的对象复制到另一块上面,然后再把刚刚用过的内存空间一次性清理掉,这样解决了碎片问题。

3)标记整理算法 Mark-Compact:

复制算法在对象存活率较高时就会频繁进行复制操作,效率将降低,因此有了Mark-Compact算法。标记过程和标记清除算法相同,但是后续不是直接清除对象,而是让所有存活的对象向同一侧移动,然后直接清理边界以外的内存。

两种算法判定对象是否存活

1)引用计数算法:给对象中添加一个引用计数器,每当一个地方应用了对象,计数器+1,当引用失效,计数器-1.计数器为0表示该对象已死,可回收。但是这个方法很难解决两个对象循环相互引用的情况。

2)可大型分析算法:通过一系列称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(即对象到GC Roots不可达),则证明对象已死,可回收。Java中可以作为GC Roots的对象包括:Jvm栈中引用的对象,本地方法栈中Native方法引用的对象,方法区静态属性引用的对象,方法区常量引用的对象。主流实现中,都是通过可达性分析算法来判定对象是否存活。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,784评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,745评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,702评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,229评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,245评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,376评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,798评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,471评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,655评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,485评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,535评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,235评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,793评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,863评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,096评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,654评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,233评论 2 341

推荐阅读更多精彩内容

  • 1、java中的内存模型 gc内存模型:主要包括栈、堆、程序计数器,其中栈和程序计数器是线程私有的 1)栈:虚拟机...
    糖豆_7986阅读 190评论 1 0
  • JVM架构 当一个程序启动之前,它的class会被类装载器装入方法区(Permanent区),执行引擎读取方法区的...
    cocohaifang阅读 1,630评论 0 7
  • Java8张图 11、字符串不变性 12、equals()方法、hashCode()方法的区别 13、...
    Miley_MOJIE阅读 3,686评论 0 11
  • 原文阅读 前言 这段时间懈怠了,罪过! 最近看到有同事也开始用上了微信公众号写博客了,挺好的~给他们点赞,这博客我...
    码农戏码阅读 5,934评论 2 31
  • 内存溢出和内存泄漏的区别 内存溢出:out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,...
    Aimerwhy阅读 725评论 0 1