jvm 整理

1、jvm有哪些组成,每一个组成的作用。

2、什么情况下会内存溢出

3、jvm的内存结构

4、JVM内存为什么要分成新生代,老年代,持久代(1.8之后没了)。新生代中为什么要分为Eden和Survivor。

5、JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代

6、你知道哪几种垃圾收集器,各自的优缺点,重点讲下 cms 、 arthas  和G1,包括原理,流程,优缺点。

7、说说你知道的几种主要的JVM参数

8、简单说说你了解的类加载器,可以打破双亲委派么,怎么打破。

9、强引用、软引用、弱引用、虚引用的区别?

 

 

 

一、jvm 的组成:

1、三大块

2、主要就是内存区域

当一个线程启动时候,就会从栈里面分配一块内存空间出来给这个线程,所以会有人叫线程栈。

在一个线程栈里面,每一个方法对应一块内存空间,也叫栈帧内存空间,同时这个内存空间也用来存方法内的局部变量。

栈帧:

first in last out 先进后出。方法执行完之后会出栈(释放内存。)这里先调用的方法是方法内的方法, 先调用的方法先分配内存,后调用的方法后分配内存,但是后调用的方法会先结束(先释放内存),这里说的应该是方法嵌套(TODO )。这里记住方法执行完就释放内存。

栈帧里面有:(他们就是内存区域)

局部变量、操作数栈、动态链接、方法出口(这四个调优的时候会用到,平时用不到)

操作数栈:程序运行过程中被操作的那些值临时存放的内存空间。

动态链接:找到方法区中的代码的作用。

方法出口:方法结束之后往哪里走。

 

程序计数器:

作用:用来记录代码即将或正在被执行的那行代码的行号。实际放的是那几行代码的内存地址。

       为什么会有程序计数器:一个线程执行过程中,一个更高优先级别的线程强了cpu之后,CPU执行中可能会中断执行这个线程(线程被挂起),当cpu重新执行这个线程的时候就需要知道代码执行到哪里了。

 

每一个线程都会被分配一块程序计数器内存空间

 

方法区(元空间)

放:常量、静态变量、类信息(类代码信息,就是字节码信息)

 

拓展:

类名右键-》open in terminal -》输入 javap 看到很多  -》输入:"javap -c Math.class -> math.txt" 

 

堆:

放对象,其他地方放的对象是堆里面对象的地址。

这里还要再看一下。下面是堆的内存:

有老年代和年轻代。老年代默认占三分之二,年轻代默认占三分之一。

new出来的对象是放到Eden (伊甸园)区。如果放满了,jvm字节码引擎会开启一个垃圾收集线程(minor gc)。

垃圾收集线程底层:(minor gc )

应用可达性分析算法。(就是先找非垃圾对象:线程栈的本地变量、静态变量、本地方法栈的变量等,找到这些,然后找相关联的被引用的对象,标记为非垃圾对象,放到survivor区中,然后把剩下在eden(伊甸园区)的清理掉,这些都是垃圾,没有被引用了。)

minor gc每次都会在年轻代内存里面找,被找15次都不是垃圾的对象。就会被移到老年代里面。

?为什么要有两个survivor 空间:

建立两块Survivor区,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)。S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。如果对象的复制次数达到16次,该对象就会被送到老年代中。

如果是一个survivor 区,容易造成碎片化内存空间。

survivor 幸存者区:有两个。

问题:eden 和survivor 内存比例:8:1:1 (不要纠结这个比例。还需要再探究,确认。)

(TODO)确认一下下面内容:

1.8之后取消了永久代,方法区概念上还是存在的,原先永久代中类的元信息会被放入本地内存,将类的静态变量和内部字符串放入到java堆中。

     

 

本地方法栈:

放本地方法的内存。native 修饰的方法,不是java代码实现的。

 

先用几个调优工具用一用:

下面这个方法,就会造成oom(内存溢出)。

为什么呢?new出来的变量一直被引用着。

jvm调优工具:

1、jdk自带的:jvisualvm

cmd 输入“jvisualvm”

 

 

上面这个很多都不用了,还有其他的调优诊断工具都不用了。

现在都用阿里出的:Arthas (jvm 调优诊断工具)

强大,简单,方便。

快速定位到内存中正在运行的代码具体在哪一行出问题。

 

jvm调优到底是干什么?目的是什么?

1、目的:

减少GC,核心目标减少full GC。为什么?

STW概念(stop the world)在做full GC或者minor GC 的时候,都会停掉用户线程。full GC会更久一点。

minor gc时间非常短,一般不用关注,但是full GC 一定要关注。

问题:为什么会有STW的机制?

不要让用户线程的执行影响到对象是否是垃圾。影响到垃圾回收。

2、full GC:

    在老年代放满的时候,jvm字节码引擎会使用full GC 对整个堆进行垃圾收集。

如果收集之后内存还是放不下,就会内存溢出(oom)。

3、阿里面试题:

能否对jvm进行调优,让其几乎不发生full GC。

把年轻代内存调大一点。减少 minor gc 频率,减少进入full GC的对象大小。

让生命周期短的对象在minor gc 就被清理回收。

 

垃圾收集器:

 

 

单机几十万超高并发的系统调优

1、kafka 、rocketmq 单机并发都能到达十万以上。但是需要jvm调优。

大内存服务器。eden 30G 

如果等30G满了才触发一次minor GC,那么就会回收很长时间可能几十秒。这样就会出现请求超时。

G1核心思想:每次minor GC 不用等eden(伊甸园区)内存区域满了才去收集。而是先收集其中eden中的一部分内存,比如两个G的内存,可以几十毫秒收集完成,收集完之后新的对象放在刚刚收集过的内存块,然后再去收集其他部分内存。

    目的就是为了不能让GC时间太长。

1.1、加上下图这个这个:告诉jvm 采用G1 的垃圾收集机制。

1.2、加上下图这个这个:告诉jvm minor gc 的停顿时间最多不超过100ms。jvm 采用G1的算法,计算出一块内存区域需要回收100ms,就回收那一块区域。(cms垃圾收集器底层就没有这些机制)

G1:

 

 

2、jvm联合实际项目调优。

 

 

还没写完,整理,后续会更新。

 

长路漫漫,继续加油!!!

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值