JVM总结&GC垃圾回收

问题:

1.你对JVM的理解。

答:jvm是Java运行虚拟机,主要是为了跨平台,一次编译到处执行。

2.Java8的虚拟机有什么更新

答:撤销了永久带,引入了元空间。

元空间内的规则:元空间中类及其相关的元数据和类加载器生命周期一致,每个类加载器有专门的存储空间,不会单独回收某个类,位置也是固定的,但是当类加载器不再存活时会把它相关的空间全部移除。

 

3.什么是OOM。

答:java.lang.OutOfMemoryError: java heap space异常,说明Java虚拟机的堆内存不够。

原因:

  • java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整
  • 代码中创建了大量的大对象,并且长时间不能被垃圾回收器收集,存在被调用

 

4.什么是StaticOverFlowError?有哪些方法分析。

栈溢出,不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,导致数据越界,结果覆盖了老的堆栈数据。

5.JVM常用参数调优。

初始的要和最大的内存设置一致

  • -XX:PrintGCDetails   日志解析
  • -XX:SurvivorRatio=6 ,设置的是Eden区与每一个Survivor区的比值,可以反推出占新生代的比值,Eden为6, 两个Survivor为2, Eden占新生代的3/4, 每个Survivor占1/8,两个占1/4
  • -XX:NewRatio=4  新生代(Eden + 2*S)与老年代(不包括永久区)的比值;要求比较的高的吞吐量(避免较多的fullGC) 4 表示新生代 :老年代 = 1:4 ,意思是老年代占 4/5 
  • -XX:MaxTenuringThreshold  设置垃圾最大年龄  默认15

在IDEA设置JVM参数

run 》Edit Configurations..

 

6.你对JVM类加载器的认识。

大体分为三个(虚拟机自带加载器)

  1. 启动类加载器(Bootstrap)C++
  2. 扩展类加载器(Extension)Java
  3. 应用程序类加载器(AppClassLoader) 系统类加载器,加载当前应用所用到的classpath的所有类

增加:(用户自定义类加载器):Java.lang.ClassLoader的子类,用户自定义类的加载方式

 

总结

 

JVM体系结构
JVM体系结构

 

类加载器ClassLoader

负责加载class文件,class文件在文件开头有特定的文件标志,cafe babe ,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据并且ClassLoader只负责class文件的加载,如何运行由Execution Engine决定

类.class - ClassLoader - 加载并初始化- 类Class -对象实例

public class Test01 {
    public static void main(String[] args) {
        Test01 test01 = new Test01();
        System.out.println(test01.getClass());
        System.out.println(test01.getClass().getClassLoader());
        System.out.println(test01.getClass().getClassLoader().getClass().getClassLoader());
    }
}

class com.qyc.jvm.Test01
sun.misc.Launcher$AppClassLoader@18b4aac2
null

 方法区

  • 它存储了每个类的结构信息
  • 方法区是规范,在不同虚拟机里头实现是不一样的,永久代(PermGen space) 和元空间(Meta space)
  • 方法区 object = new 永久代/元空间

栈管运行,堆管存储

Stack栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命周期时跟随线程的生命周期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束,该栈就Over,生命周期和线程一致,是线程私有的。

8种基本类型的变量+对象的引用变量+实例方法都是在函数的栈内存中分配。

栈帧

主要保存三种数据

  1. 本地变量(Local Variables):输入输出参数
  2. 栈操作(Operand Stack):记录出栈、入栈的操作
  3. 栈帧数据(Frame Data):包括类文件、方法等

Heap堆(Java7之前)

一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行。(java8以后叫 元空间)

新生代:1/3

Eden:8/10

From:1/10

To:1/10

Old:老年代 2/3堆空间

 

 

栈、堆、方法区的交互关系

  1. HotSpot是使用指针的方式来访问对象
  2. Java堆内存会存放访问类元数据的地址
  3. refernece存储的就是直接是对象的地址

MinorGC的过程(复制->清空->互换)

1.eden、SurvivorFrom 复制到SurvivorTo ,年龄+1

首先,Eden区满的时候会触发第一次GC,把还活着的对象拷贝到SurvivorFrom,当Eden区再次触发GC的时候会扫描Eden区和From区域,对这俩个区域就行垃圾回收,经过这次回收,经过这次回收后还存活的对象,则直接复制到To区域(如果度偶对象的年龄已经达到了老年的标准,则赋值到老年代),同时把这些对象的年+1。

2.清空eden、SurvivorFrom

然后,清空Eden和SurvivorFrom中的对象,也即复制之后有交换,谁空谁是to

3.SurvivorTo和SurvivorFrom互换

最后,SurvivorTo和SurvivorFrom互换,愿SurvivorTo成为下一次GC时的SurvivorForm区。部分对象会在From和To区域中复制来复制去,如此交换15次(有JVM参数MaxTenuringThreshold决定,这个参数默认是15),最终如果还是存活,就存入到老年代。

 

GC垃圾回收

 

 

JVM在进行GC时,并非每次都对上面三个内存区域一起回收的, 大部分时候回收的都是指新生代。

因此GC按照回收的区域又分了两种类型,一种是普通GC (minor GC),一种是全局GC (major GC or Full GC)

Minor GC利Full GC的区别

普通GC (minor GC) :只针对新生代区域的GC,指发生在新生代的垃圾收集动作,因为大多数Java对象存活率都不高,所以

Minor GC非常频繁,一般回收速度 也比较快。

全局GC (major GC or Full GC) :指发生在老年代的垃圾收集动作,出现了Major GC,经常会伴随至少一次的Minor GC (但

并不是绝对的)。Major GC的速度一般要比Minor GC慢上10倍以上
 

1.引用计数算法

应用:微软的COM/ActionScript3/Python..

缺点:

  • 每次对对象赋值时均要维护引用计数器,且计数器本身也有一定的消耗
  • 较难处理循环引用

2.复制算法(Copying)

缺点:

  • 它浪费了一半的内存
  • 如果对象的存活率很高,我们可以极端一点,假设时100%存活,会造成很大的资源浪费

克服50%的内存浪费。

 

3.标记清除(Mark-Sweep)

  • 老年代一般由标记清楚或者标记清除与标记整理混合使用
  • 算法分成标记和清除俩个间断,先标记出要回收的对象,然后统一回收这些对象

优点:不需要额外空间

缺点:俩次扫描,会产生内存碎片

 

4.标记压缩(Mark-Compact)

老年代一般由标记清除或者标记清除与标记整理的混合实现

优点:没有碎片

缺点:需要移动对象

 

标记清除压缩(Mark-Sweep-Compact)

原理:

  1. Mark-Sweep和Mark-Compact的结合
  2. 和Mark-Sweep一致,当进行多次GC后才Cmpact

优点:减少移动对象的成本

 

没有最好的算法,只有最适合的算法---------分代收集算法

年轻代 复制算法,通过hotspot中的俩个survivor的设计得到缓解

 

老年代  区域大,对象存活率高  标记清除,标记清除整理混合实现

 

 

 

问题

1.JVM内存模型以及分区,需要详细到每个分区放什么

 

2.堆里面的分区,Eden、survival from to ,老年代各自的特点

答:新生区时类的诞生成长小王的区域,一个类在这里产生,应用最后被垃圾回收器收集,结束生命。

Eden:当Eden区用完后程序又需要创建对象,JVM垃圾回收器将堆Eden区进行Mibor GC,然后将Eden区中不再被其他对象引用的对象进行销毁,剩余的已达到幸存0区,若0区也满了,再对该区进行垃圾回收然后属于的移动到1区,如果1区满了移动到养老区,养老区满了将产生MajorGC  (FUllGC) ,进行养老区的内存清理,若还有没有空间存储对象,那就报OOM异常,OutOfMemoryError

3.GC的三种收集方法,标记清除,标记整理,复制算法的原理与特点,分别用在什么地方

 

4.Minor GC与Full GC分别在什么时候发生

 

Volatile

volatile是Java虚拟机提供的轻量级的同步机制

  1. 保证可见性
  2. 不保证原子性
  3. 禁止指令重排序

 

JMM

  • 可见性
  • 原子性
  • 有序性

 

JMM(Java内存模型Java Memory Model)本身是一种抽象的概念,并不真实存在,描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和结构数组对象的元素)的访问方式

 

由于JVM运行程序的实体是线程,面每个线程创建时JVM都会为其创建一个工作内存(有些地方称为栈空间),工作内存是每个线程的私
有数据区域,而Java内 存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读
取赋值等)必须在工作内存中进行,首先要将变量从主内存拷贝到的线程自己的工作内存空间,然后对变量进行操作,操作完成后再将变
量写回主内存,不能直接操作主内存中的变量,各个线程中的工作内存中存储着主内存中的变量副本拷贝,因此不同的线程间无法访问
对方的工作内存,线程间的通信(传值)必须通过主内存来完成,其简要访问过程如下图:
 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值