JVM入门笔记整理

Java体系结构

image-20210314213938417

类加载器

作用

加载Class文件

流程

image-20210314214851228

image-20210315160050710

双亲委派机制

当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。

类的加载是现在根加载器BOOT中寻找是否有,如果没有就从拓展类加载器里面找,再没有才从自己的应用程序加载器里面找。rt.jar就是java核心的加载器

在介绍双亲委派机制的时候,不得不提ClassLoader(类加载器)。说ClassLoader之前,我们得先了解下Java的基本知识。

Java是运行在Java的虚拟机(JVM)中的,但是它是如何运行在JVM中了呢?我们在IDE中编写的Java源代码被编译器编译成.class的字节码文件。然后由我们得ClassLoader负责将这些class文件给加载到JVM中去执行。
JVM中提供了三层的ClassLoader:

BootstrapClassLoader(启动类加载器)

c++编写,加载java核心库 java.*,构造ExtClassLoader和AppClassLoader。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作

ExtClassLoader (标准扩展类加载器)

java编写,加载扩展库,如classpath中的jre ,javax.*或者
java.ext.dir 指定位置中的类,开发者可以直接使用标准扩展类加载器。

AppClassLoader(系统类加载器)

java编写,加载程序所在的目录,如user.dir所在的位置的class

CustomClassLoader(用户自定义类加载器)

java编写,用户自定义的类加载器,可加载指定路径的class文件

自己的见解

1 类加载器收到类加载请求

2 将这个请求向上委托给父加载器去完成,一直向上委托 直到启动类加载器

3启动类加载器检测是否能加载这个类,能加载就结束,使用当前的加载器,否则,抛出异常,通知子加载器进行加载

4重复步骤三 如果最后都没有加载,那就抛出异常

native

凡是带了native关键字就说明java的作用范围达不到了,回去调用底层c语言的库

会进入本地方法栈

调用本地方法接口 JNI java native interface

JNI作用:拓展java的使用,融合不同的语言为java所用

java诞生的时候,c和c++横行,想要立足就必须调用c和c++的程序

他在本地内存区域中专门开辟了一块内存区域,也就是 本地方法栈 作用:登记native方法

在最终执行的时候,加载本地的方法库中的方法 通过JNI

应用场景:Java程序驱动打印机,或者就是管理系统,还有就是reboot外挂

方法区

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

static final Class 常量池

字符串常量池在堆里面,运行时常量池在方法区里面

存放八大基本类型,对象引用,实例的方法

image-20210315174121577

堆 Heap

一般使用的就是sun公司的HotSPot

一个jvm只有一个堆内存,堆内存的大小可以调节

类加载器读取文件后,一般把类,方法,常量,变量,保存引用类型真实的对象

三个区域

新生区

养老区

永久区

image-20210315175726629

GC垃圾回收,主要是在新生区和养老区

假设内存满了,OOM,内存不够;

在jdk8以后,永久区改了个名字(元空间)

新生区

  • 类:诞生和成长的地方

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

  • 幸存者区 (0,1)

    image-20210315192221977

永久区

这个区域常驻内存,用来存放jdk自身携带的Class对象,interface元数据,存储的是Java运行时的环境或类信息,这个区域不存在垃圾回收

关闭虚拟机就会释放这个区域的内存

永久区一般不会存在OOM

特殊情况:一个启动类,加载了大量的第三方jar包。Tomcat部署了太多的应用,大量动态生成的反射类,不断地被加载,直到内存满了,就会出现OOM;

应用

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

  • 能够看到第几行出错:内存快照分析工具 MAT Jprofile
  • debug 一行一行分析代码

Jprofile作用:

  • 分析Dump分析内存文件,快速定位内存泄漏
  • 获取堆中的数据
  • 获取大的对象

命令:

-Xms1m -Xmx1m -XX:+HeapDumpOnOutOfMemoryError

-Xms  //设置初始化内存分配大小  默认 1/64
-Xmx  //设置最大分配内存 默认  1/4
-XX:+PrintGCDetails  //打印GC清理信息
-XX:+HeapDumpOnOutOfMemoryError  //oom  dump

dump文件

Dump文件是进程的内存镜像。可以把程序的执行状态通过调试器保存到dump文件中。Dump文件是用来给驱动程序编写人员调试驱动程序用的,这种文件必须用专用工具软件打开,比如使用WinDbg打开。

在jvm调优的时候,可以通过生成dump文件,然后再分析文件,就可以了解程序发生错误具体的位置

GC:垃圾回收

作用区域

image-20210315203404898

JVM在进行GC时,并不是对这三个区域统一回收,大部分时候,回收都是新生代。

  • 新生代
  • 幸存区(from to)
  • 老年区

GC种类

轻GC 普通的GC

重GC 全局的GC

GC的算法

标记清除法

image-20210315205722952

缺点

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

优点

不需要额外的内存空间

标记压缩

image-20210315210027868

复制算法

image-20210315205023635

image-20210315205310996

好处

没有内存的碎片

坏处

浪费了内存空间 多了一般空间永远都是空的,假设对象百分之百存活(极端情况)

最佳使用场景

对象存活度较低的时候

引用计数器

image-20210315204216120

总结

比较

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

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

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

最优算法

没有最优的算法,只有最合适的算法,各个场景有不同的最合适的的算法 GC也就是分代收集算法

分代收集算法

​ 当前商业虚拟机的垃圾收集都采用“分代收集”(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适合的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成。而老年代中因为对象存活率高、没有额外空间对他进行分配担保,就必须使用“标记-清理”或者“标记-整理”算法来进行回收。

image-20210315210906138

JMM java memory model

image-20210315212420666

解决措施

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bfKKgDgD-1615882074123)(C:\Users\青城小叶\AppData\Roaming\Typora\typora-user-images\image-20210315212540113.png)]

image-20210315212819354

优化措施

image-20210316154925681

数据库优化,数据库查询的字段可以增加索引,等等还有很多数据库优化的方式

nginx和gateway优化,可以增加带宽或者增加内存

thymeleaf优化,可以打开缓存,这样也可以有一定的优化

在生产环境中还可以选择把日志等这些没必要的东西关闭

由于需要获取静态资源,而这些静态资源就是不需要经常改变的资源,所以可以做到动静分离,将静态资源放到nginx中,同时设置相应的规则,这样就可以减少业务

还有就是业务优化,减少循环查表,可以一次性全部查出来,然后要查询的时候,就遍历已经查询的集合

还有就是可以增加内存(增加默认内存和最大内存) 还有增加老年区,新生区的内存

image-20210316155544272

监控工具

监控工具可以采用jdk自带的jvisualvm

直接在控制台数据jvisualvm就可以了,但是需要增加GC插件,这样就可以查看堆的使用情况,也就是新生区,老年区,伊甸园区,还有就是cpu使用情况,如果cpu使用率高,或者内存高,就可以采取合适的优化方式

压力测试工具可以采用apache-jmeter-5.4.1,具体使用就不说了,到时候可以直接百度

时候,就遍历已经查询的集合

还有就是可以增加内存(增加默认内存和最大内存) 还有增加老年区,新生区的内存

[外链图片转存中…(img-hpEcRqsk-1615882074125)]

监控工具

监控工具可以采用jdk自带的jvisualvm

直接在控制台数据jvisualvm就可以了,但是需要增加GC插件,这样就可以查看堆的使用情况,也就是新生区,老年区,伊甸园区,还有就是cpu使用情况,如果cpu使用率高,或者内存高,就可以采取合适的优化方式

压力测试工具可以采用apache-jmeter-5.4.1,具体使用就不说了,到时候可以直接百度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值