jvm快速入门

JVM快速入门

一、JVM的体系结构

1、位置

在这里插入图片描述

  • JVM说到底就是一个程序
  • JRE中包含JVM,也就是这些Java程序都是跑在JRE这个环境中的
  • Java的运行环境是跑在操作系统上的
  • 操作系统是跑在硬件上的

2、结构

在这里插入图片描述

二、类加载器及双亲委派机制

在这里插入图片描述

1、类加载器

在这里插入图片描述

  1. 虚拟机自带的加载器
  2. 启动类(根)加载器

rt.jar包下的类

  1. 扩展类加载器

image-20230306210253116

  1. 应用程序加载器

image-20230306210211537

2、双亲委派机制

image-20230306211027345

  • 从上图可以看出,我们创建一个同包同名的String类,然后在main中运行,报错

image-20230306211148727

  • 这里用到了双亲委派机制,说到底还是为了安全,这里new String时,就会根据优先级去使用 App -》 Ext -》 ROOT 中去加载类,如果ROOT中没有就找Ext,如果Ext没有就找App

流程

  1. 类加载器收到类加载的请求
  2. 将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
  3. 启动加载器检查是否能够加载当前这个类,能加载就结束,使用当前的加载器,否则,抛出异常,通知子加载器进行加载
  4. 重复步骤3

三、Native、PC寄存器、方法区

1、native

      凡是带了native关键字的,说明java的作用范围达不到了,获取调用C语言的库,会进入本地方法栈,调用本地方法接口 JNI
     JNI作用:扩展Java的使用,融合不同的变成语言为Java所用,最初就是去使用C、C++,它在内存中专门开辟了一个快内存Native Method Stack,等级Native方法,在最终执行的时候,加载本地方法库中的方法通过JNI,例如Java程序的的打印机,管理系统,掌握即可,在企业应用中较为少见

2、PC寄存器

程序计数器: Program Counter Register

     每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向像条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计

3、方法区

Method Area 方法区

      方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间

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

四、深入理解栈

  • 栈是一个数据结构

程序 = 数据结构 + 算法
程序 = 框架 + 业务逻辑

  1. 栈:先进后出、后进先出:桶
    队列:先进先出(FIFO:First Input First Output)

  2. 栈:栈内存,主管程序的运行,生命周期和线程同步,线程结束,栈内存也就释放了,对于栈来说,不存在垃圾回收机制

  3. 栈:8大基本类型 + 对象引用 + 实例的方法

  4. 栈的运行原理:栈帧

在这里插入图片描述

对象实例化的过程

在这里插入图片描述

五、走进HotSpot和堆

  • 三种JVM
  1. Sun公司 HotSpot Java Hotpot™ 64-Bit Server VM (build 25.181-b13, mixed mode)
  2. BEA JRockit
  3. IBM 39 VM

     Heap,一个JVM只有一个堆内存(栈是线程级的,一个线程有一个栈,所以堆需要垃圾回收),堆的大小是可以调节的

     类加载器读取了类文件后,一般会把类、方法、常量、变量放到堆中去

  • 堆内存中还要细分为三个区域:
  1. 新生区(伊甸园):Young/New
  2. 养老区:old
  3. 永久区:Perm

在这里插入图片描述

GC垃圾回收,主要是在伊甸园和养老区~如果是内存满了的话,就会出现OOM,堆内存不够

如果伊甸区满了就会触发一次轻GC,存活下来的就会跑到幸存区(这里有两个,不停地切换),如果伊甸区和幸存区都满了的话就会触发一次重GC,存活下来的就会跑到养老区中,如果都满的话,就会发生OOM

在jdk8以后,永久存储区变了一个名字叫做元空间

六、新生区、永生区,堆内存调优

1、新生区

  • 类:诞生和成长的地方,甚至死亡
    • 伊甸园,所有的对象都是在伊甸区new出来的
    • 幸存者区(0,1)

经过研究,99%的对象都是临时对象

2、永久代

     这个常驻内存,用来存放JDK自身携带的Class对象,Interface元数据,java运行时的一些环境或类信息,这个区域不存在垃圾回收机制,关闭VM虚拟就会释放这个区域的内存

     一个启动类,这个区域加载了大量的第三方jar包,tomcat部署了太多的应用,或者大量动态生成的反射类。如果他们被不断的加载
v

  • jdk1.6:永久代,常量池是在方法区中
  • jdk1.7:永久代,但是慢慢的退化了,去永久代,常量池在堆中
  • jdk1.8:无永久代,常量池在元空间

在这里插入图片描述

元空间:逻辑上存在,物理上不存在
-Xms1024m -Xmx1024m -XX:+PrintGCDetails
305664K+699392K = 981.5MB

在这里插入图片描述

在一个项目中,突然出现了OOM故障,那么该如何排除~研究为什么出错

  • 能够看到代码第几行出错
  • Debbug,一行行看错

3、OOM

出现原因就是堆内存满了

解决方案:

  1. 尝试扩大堆内存

-Xms数值m -Xmx数值m -XX:+PrintGCDetails

  1. 如果还有错误,就分析内存,看一下是哪里出了问题(视频中使用的是Jprofiler)

下载jprofiler9,在idea中下载jprofiler插件,然后再设置的tools中的去配置jprofiler,选择你安装的jprofiler的目录下的bin里面那个后缀为exe的文件

使用Jprofiler去分析内存

  • -Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError(dump出什么异常的命令)在VM处修改,然后启动
    在这里插入图片描述

  • 就可以在该java的文件的项目目录中看到dump出的文件了
    在这里插入图片描述

  • 这里就可以看见这个异常的地方了,通过看那个线程的甚至还能直接定位到报错的行数
    在这里插入图片描述

在这里插入图片描述

七、GC

大名鼎鼎的垃圾回收机制

在这里插入图片描述

  • JVM在进行GC时,并不是对这三个区域统一回收的。大部分的时候,回收的都是新生代
    • 新生代
      • 伊甸园区
      • 幸存区 (from 、 to)
    • 老年区
  • GC:轻GC(普通GC)、重GC(全局GC)

1、GC的常用算法

  1. 标记清除法
  2. 标记整理法(标记压缩)
  3. 复制算法
  4. 引用计数器

2、引用计数法

在这里插入图片描述

通过给对象分配一个计数器,然后引用一次就加一来判断哪个没用了,进行回收,但是分配计数器本身也有消耗空间,用的比较少

3、复制算法

     这里涉及到了幸存区0,幸存区1,来回切换的问题,记住一个口诀谁空谁是to

  1. 比如,第一次GC的时候,存活下来的对象先到了一个幸存区中,这个幸存区就叫做from,另一个叫to
  2. 如果当又来一次gc的时候,存活下的对象就会先到to中,此时from,to都有对象了,此时,他就会将form中的对象复制到to中,然后之前那个from幸存区又变成了to,继续接受存活的对象并接受from中复制来的对象
  3. 之后一个对象如果经过了指定此处的gc还没有死的话,就会进入到老年区

在这里插入图片描述
好处:没有内存的碎片
坏处:浪费了内存空间:多了一半空间永远是空的

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

4、标记清除算法

在这里插入图片描述

优点:不需要额外的空间
缺点:两次扫描,严重浪费时间,会产生垃圾碎片

5、标记压缩清除算法

先标记,再压缩

在这里插入图片描述

八、总结

  • 内存效率:复制算法 > 标记清除算法 > 标记压缩算法(时间复杂度)
  • 内存整齐度:复制算法 = 标记压缩算法 > 标记清除算法
  • 内存利用率:标记压缩算法 = 标记清除算法 > 复制算法

有没有最优的算法?

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

年轻代

  • 复活率低
  • 复制算法!

老年代

  • 区域大:存活率
  • 标记清除(内存碎片不是太多) + 标记压缩混合 实现
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值