天天看点

JVM知识点复习(第一次)

最为一个java的初学者,其实可以不用太细致的学习java虚拟机,不过如果你是有一定的工作经验了,那JVM绝对是一个不应该绕开的点。具体的讲解可以参考周志明的《深入理解Java虚拟机》,如果是深度学习,建议还是看书。如果是作为了解大致,可以看看网上的视频,再来点博客差不多了。各个视频针对的JDK版本记住要看清楚,每个版本的JDK都或多或少有些差别,不要迷了眼。

文章目录

    • 1、JVM概述
      • 1.1、JVM位置
      • 1.2、JVM体系结构
    • 2、类加载器
      • 2.1、模板类
      • 2.2、类加载器的分类
    • 3、沙箱安全机制
    • 4、Native
    • 5、PC寄存器
    • 6、方法区
    • 7、栈
    • 8、三种不同的JVM
    • 9、堆(重点)
      • 9.1、新生区、老年区、永久区
      • 9.2、对内存调优
      • 9.3、GC垃圾回收
    • 10、JMM
    • 11、思维导图

1、JVM概述

1.1、JVM位置

我们都知道java是一个跨平台的语言,其跨平台的特性则是由于虚拟机的存在。

那JVM虚拟机到底在哪里呢?

我们的OS系统是部署在计算机硬件之上,我们的JVM则是部署在OS之上,再往上走,就是我们编写程序了。

1.2、JVM体系结构

我们程序的执行顺序是:我们编写的.java文件经过编译生成.class文件,然后再将我们的.class文件交给类加载器,然后再执行相应的操作。

JVM知识点复习(第一次)

这个图有些笼统,不过大致的体系结构就是这样,可以当作一个入门的体系结构图示

我经常在网上看到内存调优这个关键词,它更多的指的位置就是在对JVM中堆内存的调节。

2、类加载器

2.1、模板类

在java的进阶阶段,我们学习过反射,我们也都知道,所有的对象都是来自于一个类模板的Class。就好比一个Student类所创建的所有的对象,都来自于Student.class这个模板,这些所有创建出来的对象,都来自同一个地方。

2.2、类加载器的分类

随着JDK版本的变化,可能名称有些许出入

1、根加载器

2、扩展加载器

3、系统加载器

4、自定义加载器

当然这里还出现了一个很重要的双亲委派机制

3、沙箱安全机制

java用来保证程序安全引入的一种安全机制

4、Native

结合我们类加载器的知识点,凡是带有native关键字的,都说明这是java作用范围达不到的,它回去调用底层的C语言的库。

带有native关键字的方法就会进入到本地方法栈,其他的会进入java栈

本地方法接口(Native Interface):起初是为了融合C/C++,现在大多可用于驱动底层的硬件

本地方法栈(Native Method Stack):在本地方法栈中登记native方法,在执行引擎的时候加载本地库(Native Libraies)

5、PC寄存器

又名程序计数器Program Counter Register

PC寄存器为每一个线程所私有,占用内存十分小。用于记录各个线程正在执行的字节码指令地址。

6、方法区

该区域可以与PC寄存器形成鲜明的对比,它是被线程所共享。

我们常见的static、final、Class模板、常量池都存在于方法区。

7、栈

我们一想到栈首先应该想到的就是与它齐名的队列。

栈(木桶):先进后出

队列(水管):先进先出

栈中存放的东西:八大基本类型 + 对象的引用 + 实例的方法

当栈满了以后,就会出发栈满异常StackOverflowError

我们还有一个堆没有学习,学习玩堆以后,我们对于实例化一个对象,并且赋值调用的整个流程,心里应该是要有一个流程图了。

8、三种不同的JVM

  • Sun:HotSpot(我们使用的)
  • BEA:JRockit
  • IBM:J9 VM

9、堆(重点)

我们前面说了基本上的JVM调优,指的就是堆调优

堆内存主要分为:新生区(伊甸园区)、养老区、永久区

9.1、新生区、老年区、永久区

对象最开始产生的地方是伊甸园区,当伊甸园区满了以后就会触发第一次GC(轻GC),存活下来的对象就会进入到幸存者区。当幸存者区也满了以后,就会再触发GC(重GC),然后依然存活的对象就会进入养老区

如果养老区满了以后就会报堆满异常OOM:

java.lang.OutOfMemoryError:Java heap space

当然,JDK不同的版本,具体的细节又有些差别,特别是名字

我的观点是,现在公司大部分使用的是JDK1.8,我们要做的就是记住1.8的就好了。但是巧就巧再没有专门说1.8的书,《深入理解java虚拟机》的第二版是JDK1.7,第三版是JDK12,13左右…那就只有官方文档加实践了。

9.2、对内存调优

我们前面说了,轻GC和重GC是可以用来处理堆内存的垃圾对象的。那么多久用一次轻GC?多久又用一次重GC?甚至是堆内存异常的时候,我们怎么排查呢?

所以对内存调优就是为了排查出异常,排查方式可分为两种:

  • 使用Debug一行一行看
  • 使用内存快照分析工具,如MAT、Jprofiler

9.3、GC垃圾回收

垃圾回收算法有哪些?

复制算法、标记清除算法、标记压缩算法

==复制算法:==伊甸园区的对象总是进入幸存区的from区,与此同时,幸存区的to区的数据也进入from区(幸存区的from区和to区是随时变化的)。所以每次伊甸园区的数据进入from区的时候,该区总是空的。

==标记清除算法:==对所有的对象进行扫描,然后对活着的对象进行标记,第二次扫描的时候,对于没有标记的对象进行清除。

==标记压缩算法:==在标记清除算法的基础上,我们被清除的兑现过的空间位置是不连续的,就会产生内存碎片。此算法主要是讲空间进行压缩,让存活的对象进行移动,是内存碎片变成大的内存空间。

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

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

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

没有最好的算法,只有最合适的算法,即GC也称为分代收集算法

年轻代:存活率低,使用复制算法

老年代:区域大存活率高,使用标记清除(内存碎片不是太多)+标记压缩算法混合实现

10、JMM

Java内存模型(Java Memory Mode)

核心概念:我们的每一个线程的工作内存和主存之间存在一个抽象关系,即线程之间的共享变量存储在主内存重,每一个线程都有一个私有的本地内存。

11、思维导图

JVM知识点复习(第一次)