JVM探究 随笔

JVM探究

  • 谈谈对JVM理解? java8虚拟机和之前的变化?

  • 什么是OOV ? 什么事栈溢出? 怎么分析?

  • JVM的常用调优?

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

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

JVM的位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Obh4E7Y-1617090571431)(JVM.assets/image-20210330083801211.png)]

JVM的体系结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DRrT1YHU-1617090571433)(JVM.assets/image-20210329234126028.png)]

类加载器

作用: 加载Class文件

  1. 根类加载器(bootstrap class loader): 加载 Java 的核心类
  2. 扩展类加载器(extensions class loader: 加载lib/ext或者由java.ext.dirs系统属性指定的目录中的JAR包的类
  3. 系统类(应用程序)加载器(system(application) class loader):它负责在JVM启动时加载来自Java命令的-classpath选项、java.class.path系统属性,或者CLASSPATH换将变量所指定的JAR包和类路径。

双亲委派机制

img

从上图中我们就更容易理解了,当一个Hello.class这样的文件要被加载时。不考虑我们自定义类加载器,首先会在AppClassLoader中检查是否加载过,如果有那就无需再加载了。如果没有,那么会拿到父加载器,然后调用父加载器的loadClass方法。父类中同理也会先检查自己是否已经加载过,如果没有再往上。注意这个类似递归的过程,直到到达Bootstrap classLoader之前,都是在检查是否加载过,并不会选择自己去加载。直到BootstrapClassLoader,已经没有父加载器了,这时候开始考虑自己是否能加载了,如果自己无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException。
这种设计有个好处是,如果有人想替换系统级别的类:String.java。篡改它的实现,在这种机制下这些系统的类已经被Bootstrap classLoader加载过了(为什么?因为当一个类需要加载的时候,最先去尝试加载的就是BootstrapClassLoader),所以其他类加载器并没有机会再去加载,从一定程度上防止了危险代码的植入。
————————————————
版权声明:本文为CSDN博主「IT烂笔头」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/codeyanbao/article/details/82875064

沙箱安全机制

一种保护机制,了解就够

Native

调用底层C语言的库(JNI接口)。调用native方法,会进入本地方法栈(Native Method Stack),调用本地方法接口(Java Native Interface)。

例子:Class Thread 中有 native Start0() 方法。Class Robot类,大量使用native方法,操作电脑硬件。

作用:扩展Java类的使用,融合不同的编程语言。

Native Method Stack : 内存中专门的一块标记区域,登记natvice方法。主要是硬件相关的。

PC寄存器

程序计数器:Program Counter Register

每个线程都有1个,是线程私有的。就是一个指针,指向方法区的字节码,内存占用,基本忽略不计。

方法区

方法区:Method Area

所有线程共享的。

用于存储已被虚拟机加载的类信息(Class)、常量(final)、类静态变量(Static)、常量池~

在堆中 ,元空间或者永久代。

属于数据结构的一种,这里指的是栈内存:主管程序执行,生命周期和线程同步。线程结束,栈内存也就是释放。 不存在垃圾回收问题

程序 = 数据结构 + 算法 ;

栈 :先进后出 , 后进先出;类似桶的结构;队列:相反;

用于存储 8大基本类型+对象引用+实例方法

栈满了:StackOverflowError,注意是错误,虚拟机会停。

栈内部结构图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-slw30Ogc-1617090571434)(JVM.assets/image-20210330095518022.png)]

Heap ,一个JVM只有一个堆。

类加载器读取文件后,把 类、方法、常量、变量 放入堆中。堆中保存了真实的对象。

OOM:OutOfMemoryError 堆内存满了;

Java堆内存又溢出了!教你一招必杀技

在JDK1.8版本废弃了永久代,替代的是元空间(MetaSpace),元空间与永久代上类似,都是方法区的实现,他们最大区别是:元空间并不在JVM中,而是使用本地内存。

img

img

堆内存调优

堆:默认配置是初始内存是电脑内存的1/64 , 最大内存是电脑内存的1/4;

JVM调优:依次设置初始化内存、最大内存,打印内存信息

-Xms1024m -Xmx1024m -XX:printGCDetails

内存测试工具:MAT 、 Jprofiler

  • 获取Dump文件 , 把JVM内存调小,
    • -Xms1m -Xmx8m -XX:+HeapDumpOutOfMemoryError 得到dump文件,位子在项目目录
  • 获得堆中数据
    • 使用Jprofiler打开 ,找问题 ;找大对象;

类的加载初始化

类的加载初始化:

img

  1. 创建类的对象实例需要先加载并初始化该类,main方法所在的类需要先加载和初始化

  2. 类初始化就是执行方法,对象实例化是执行方法

  3. 一个子类要初始化需要先初始化父类

  4. 类的加载机制:如果没有相应类的class,则加载class到方法区。对应着加载->验证->准备->解析–>初始化阶段

    • 加载:载入class对象,不一定是从class文件获取,可以是jar包,或者动态生成的class
    • 验证:校验class字节流是否符合当前jvm规范
    • 准备:为 类变量 分配内存并设置变量的初始值( 默认值 )。如果是final修饰的对象则是赋值声明值
    • 解析:将常量池的符号引用替换为直接引用
    • 初始化:执行类构造器( 注意不是对象构造器 ),为 类变量 赋值,执行静态代码块。jvm会保证子类的执行之前,父类的先执行完毕
  5. 其中验证、准备、解析3个部分称为 连接

  6. 方法由 静态变量赋值代码和静态代码块 组成;先执行类静态变量显示赋值代码,再到静态代码块代码

三种JVM

  • Sun公司 HotSpot
  • BEA JRockit
  • IBM J9 VM

GC

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y7ubMPLC-1617090571437)(JVM.assets/image-20210330120656858.png)]

  • 新生代
  • 幸存区
  • 老年代

GC两种类: 轻GC 与 重GC

轻GC : 主要是新生代 , 偶尔幸存区

重GC :

常用算法:

  • 标记清除法 ,

    优点: 不需要额外的空间

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HcMferrU-1617090571438)(JVM.assets/image-20210330133330087.png)]

  • 标记压缩,

    优点: 在标记清除法的基础上 , 压缩 , 防止内存碎片的产生.

    缺点: 多了一次扫描

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rTkcMoiX-1617090571439)(JVM.assets/image-20210330150722998.png)]

  • 复制算法 ,

    • 优点:没有内存的碎片
    • 缺点 : 浪费内存空间

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OUfUTzh1-1617090571441)(JVM.assets/image-20210330131730377.png)]

  • 引用计数器

每个对象都分配一个计数器 , 被调用1次就记下 . 每次扫描剔除未被调用的.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hhUGXt6U-1617090571442)(JVM.assets/image-20210330151114537.png)]

GC调优:

-XX: -XX:MaxTenuringThreshold=20 #GC 20次后进入老年代 默认是15

总结:

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

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

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

JMM内存模型

  1. 什么是JMM ?

    Java Memory Model

  2. 有什么用 ? 参考官方 , 博客 , 视频

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

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UrYyQKBi-1617090571444)(JVM.assets/image-20210330153859998.png)]

  3. 如何学习

    找到问题 , 分析问题 ,解决问题 ,触类旁通