跟着狂神学JVM

目录

一、JVM的位置

二、JVM的体系结构

1、java是谁编译成class的?

三、类加载器

作用:

分类:

双亲委派机制:

四、native关键字、PC寄存器、方法区

native:

PC寄存器:

方法区:

五、栈

栈的执行原理

​编辑

五、堆

1.新生区

轻GC和重GC分别在什么时候发生?

2.永久区

堆内存调优

发生OOM时可以怎么做?

使用Jprofiler工具分析OOM原因

六、GC(分代收集算法)

引用计数法

复制算法

标记清除

标记压缩

总结

七、JMM

前言

请你谈谈你对JVM的理解? java8虚拟机和之前的变化更新?

什么是OOM,什么是栈溢出StackOverFlowError?怎么分析?

JVM的常用调优参数有哪些?

内存快照如何抓取,怎么分析Dump文件?

谈谈JVM中,类加载器你的认识?

  1. JVM的位置

  2. JVM的体系结构

3.类加载器

4.双亲委派机制

5.沙箱安全机制(了解)

  1. Native(重点)

  2. PC寄存器(了解)

8.方法区

9,栈

10.三种JVM

11.堆

12.新生区、老年区

13.永久区

14.堆内存调优

  1. GC

    1.常用算法
    
  2. JMM

17.总结

一、JVM的位置
JVM在操作系统之上,是JRE的一部分。它是一个虚构出来的计算机

二、JVM的体系结构
1、java是谁编译成class的?

具体来说是javac将java代码文件变成java中间字节码,也就是class文件.

从体系图里看出javac是jdk的部分.Tool&toolAPIs…编译完成的中间码再在运行的时候,由Java体系的ClassLoader加载进虚拟机,再通过JIT编译成NativeCode机器指令集…最终在芯片上执行

JVM架构图

JVM架构图详细版
三、类加载器
作用:
加载class文件

分类:
启动类加载器(也叫根加载器):根加载器加载rt.jar

扩展类加载器:扩展类加载器加载ext目录下的jar

应用程序类加载器(也叫系统类加载器)

自定义加载器

双亲委派机制:
当类加载器收到类加载请求,会将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器,启动类加载器会检查是否能够加载当前这个类,能加在就结束,使用当前的加载器,否则抛出异常通知子加载器进行加载。

四、native关键字、PC寄存器、方法区
native:
凡是带了native关键字的,说明java的作用范围达不到了,会去调用底层C语言的库

会进入本地方法栈,调用本地方法本地接口

JNI作用:扩展Java的使用,融合不同的编程语言为Java所用

PC寄存器:
每一个线程都有一个PC寄存器

方法区:
静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关

五、栈
栈:有几个线程就有几个栈

栈:先进后出,后进先出

栈内存,主管程序的运行,生命周期和线程同步

不存在垃圾回收问题

栈:八大基本数据类型+对象引用+实例的方法

栈的执行原理

五、堆
一个JVM只有一个堆内存,堆内存的大小是可以调节的

堆内存中还要细分三个区域:

新生区(伊甸园区)
养老区
永久存储区

GC垃圾回收,主要在伊甸园区和养老区

假设内存满了,会报OOM,堆内存不够 java.lang.OutOfMemoryError:java heap space

在JDK8以后,永久存储区改了一个名字叫元空间

1.新生区
类诞生和成长的地方,甚至死亡;

伊甸园区:所有的对象都是在伊甸园区new出来的

幸存者区(0,1)

轻GC和重GC分别在什么时候发生?
如果新对象在创建时,因为新生区内存已满而无法创建时,这时就会发生一次轻GC,把新生区和幸存0区中的存活对象移到幸存1区,并将其他对象清除。故 轻GC实在新生区快满时发生。

重GC主要发生在老年区。轻GC过后,若新生区和其中一个幸存区仍无法存放新对象,这时就尝试把对象移到老年区,若老年区也无法存放,这时就会触发重GC。重GC过后若能存放新对象,则创建成功,若失败,则出现OOM错误。

(常见的OOM错误有三种:

​ java.lang.OutOfMemoryError: Java heap space——堆内存溢出

​ java.lang.OutOfMemoryError: PermGen space——元空间溢出

​ java.lang.StackOverflowError——栈溢出,一般是由于死循环或递归引起

这些可以通过JVM调优进行改进。)

2.永久区
阿里二面:JVM方法区和元空间的关系到底是怎样的

   在jdk7及以前,习惯上把方法区,称为永久代。jdk8开始,使用元空间取代了永久代。

JDK 1.8后,元空间存放在堆外内存中。

本质上,方法区和永久代并不等价。仅是对hotspot而言的。《Java虚拟机规范》对如何实现方法区,不做统一要求。例如:BEAJRockit / IBM J9 中不存在永久代的概念。

现在来看,当年使用永久代,不是好的idea。导致Java程序更容易oom(超过-XX:MaxPermsize上限)

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代最大的区别在于:元空间不在虚拟机设置的内存中,而是使用本地内存。

永久代、元空间二者并不只是名字变了,内部结构也调整了。

根据《Java虚拟机规范》的规定,如果方法区无法满足新的内存分配需求时,将抛出OOM异常。

堆内存调优
Xms字面意思是最小内存,这里可以理解成初始化时的内存分配,Xmx也就是允许分配的最大内存空间。

发生OOM时可以怎么做?
1.尝试扩大对内存看结果

-Xms1024m -Xmx1024m -XX:+PrintGCDetails

运行-Xms1024m -Xmx1024m,你得到的值totalMemory()和maxMemory()将是相等的

2.分析内存,看下哪一个地方出现了问题(内存快照分析工具JProfiler)

305664K+699392K=981.5m,可以看出元空间不使用虚拟机内存

使用Jprofiler工具分析OOM原因
-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

六、GC(分代收集算法)
伊甸园区
幸存区(0区和1区)
老年区
JVM在进行GC的时候,并不是对这三个区域统一回收,大部分时候回收的都是伊甸园区

GC的两个种类:轻GC(普通的GC),重GC(全局GC)

GC题目:

JVM的内存模型和分区,详细到每个区放什么?
堆里面的分区有哪些?Eden,from,to,老年区 说说他们的特点。
GC的算法有哪些?标记清除,标记压缩,复制算法,引用计数器,怎么用的?
轻GC和重GC分别在什么时候发生?
引用计数法
没讲全,引用计数法是对象被引用了计数器+1,引用结束-1,计数器为0就会被回收

复制算法
To区放不下了,剩下的全部晋升到养老区,养老区也放不下直接Full GC,Full GC后还放不下,抛出OOM

好处:没有内存碎片

坏处:浪费了内存空间,多了一半空间永远是空的

复制算法最佳使用场景:对象存活度较低的时候

标记清除
优点:不需要额外空间

缺点:两次扫描,严重浪费时间,会产生内存碎片

标记压缩
优点:不会产生内存碎片

缺点:需要三次扫描

总结
内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度)

内存整齐度:复制算法=标记压缩算法>标记清除算法

内存利用率:标记压缩算法=标记清除算法>复制算法

GC就是分代收集算法,年轻代存活率低,使用复制算法;老年代区域大,存活率高,使用标记清除+标记压缩混合实现

七、JMM
JMM就是java内存模型

它是干嘛的?

缓存一致性协议,用于定义数据读写的规则。

JMM定义了线程工作内存和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory)

解决共享对象可见性这个问题: volilate

它该如何学习?

JMM:抽象的概念,理论

你可能感兴趣的:(jvm,java,开发语言)