Java初学笔记47-【JVM】

一、JVM的位置

在这里插入图片描述

二、JVM的体系结构

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

1. 类加载器的作用

负责将.class文件给加载到JVM中去执行。

2. 类加载器分类

(1)Bootstrap classLoader:主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。
(2)ExtClassLoader:主要负责加载jre/lib/ext目录下的一些扩展的jar。
(3)AppClassLoader:主要负责加载应用程序的主函数类

3. 双亲委派机制

当一个.class文件需要被加载时,首先会在AppClassLoader中检查是否加载过,如果被加载过那就无需再加载,如果没有被加载过,会接着拿到父加载器ExtClassLoader,然后检查是否加载过,如果被加载过那就无需再加载,如果没有被加载过,会接着拿到父加载器Bootstrap classLoader进行检查是否被加载过。到此,开始从Bootstrap classLoader进行判断是否能加载,如果能加载,则加载,不能则让子类加载器ExtClassLoader、AppClassLoader依次判断去加载,如果一直到最后都无法加载,则会抛出异常ClassNotFoundException

4. 双亲委派机制的优点

防止恶意替换系统级别的类,如下图所示,想替换java.lang.String失败
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

四、沙箱安全机制

(1)限制应用程序对系统资源的访问的运行环境
(2)沙箱提供的环境相对于每一个运行的程序都是独立的,而且不会对现有的系统产生影响。

五、Native 关键字

1. Native说明

凡是带了native关键字的,说明java的作用范围达不到了,回去调用底层C语言的库。
例如线程中的start0
在这里插入图片描述

2. Native调用方式

首先进去本地方法栈中,通过java本地接口(JNIjava native interface),调用本地方法库中的方法。其中本地方法栈专门用来登记native方法。

3. JNI的作用

扩展java的使用,融合不同的编程语言为java所用。此外还可以连接硬件,如驱动打印机,管理系统等。

六、PC寄存器

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

七、方法区

  1. 方法区是被所有线程共享。
  2. 所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间;
  3. 静态变量static、常量final、类信息Class(构造方法、接口定义)、运行时的常量池,他们都存在方法区中,但是实例变量存在堆内存中,和方法区无关。

八、java类在内存实例化的过程

  1. 类实例化首先加载的是静态属性和变量、静态代码块、代码块、最后是构造函数
    在这里插入图片描述

  2. 过程
    (1)加载类的信息,类中的成员变量、方法体加载到方法区;
    (2)程序进入main方法,main函数压栈(进入栈区)同时定义了一个变量person,该变量将来指向一个Person实例对象;
    (3)在堆内存中开辟—块空间,存放new来的对象,并将其在方法区对应的成员变量、成员方法(地址值)拷贝过来,然后让栈中的变量person指向该对象示例
    (4)对new出来的person对象赋值,先在栈区找到person变量,然后根据地址值在堆中找到实例对象进行赋值操作。
    (5)当程序走到lego方法时,先到栈区找到person这个变量,然后根据该地址值在堆内存中找到实例对象,再进行方法调用。将lego方法压入栈,被调用完成后,就会立刻马上从栈内弹出,最后,在main函数完成后,main函数也会出栈。

九、堆

  1. Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的。
  2. 类加载器读取了类文件后,一般会把类,方法,常量,变量放入堆中,此外,堆还保存我们所有引用类型的实例对象;
  3. 堆内存中还要细分为三个区域:
    (1)新生区:包括伊甸园区,幸存0区,幸存1区
    (2)养老区
    (3)永久区:又名元空间
  4. 垃圾回收一般在伊甸园区,养老区
  5. 假设内存满了,出现OOM,堆内存不够! java.lang.OutOfMemoryError: Java heap space
    OOM解决方法:

(1)尝试扩大堆内存看结果

-Xms1024m -Xmx1024m -XX:+PrintGCDetails

(2)分析内存,看一下那个地方出现了问题(专业工具>

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

1. 新生区

(1)包括:伊甸园区、幸存1区、幸存2区
(2)新生区是类诞生和成长的地方,甚至死亡;
(3)所有的对象都是在伊甸园区new出来的

2. 老年区

在新生区进行轻量GC之后,若是新生区满了,在进入老年区,若是老年区满了,则会进行重量GC。

3. 永久区(元空间)

(0)元空间:逻辑上存在:物理上不存在
(1)这个区域常驻内存的。
(2)用来存放JDK自身携带的Class对象。Interface元数据,存储的是Java运行时的一些环境或类信息
(3)这个区域不存在垃圾回收
(4)关闭VM虚拟就会释放这个区域的内存。
(5)一个启动类,加载了大量的第三方jar包。Tomcat部署了太多的应用,大量动态生成的反射类。不断的被加载。直到内存满,就会出现OOM;

十一、OOM解决方法及其内存调优

java.lang.OutOfMemoryError: Java heap space

OOM解决方法:
(1)尝试扩大堆内存看结果

-Xms1024m -Xmx1024m -XX:+PrintGCDetails

(2)用能够看到代码是第几行出错的工具:内存快照分析工具。如:MAT,Jprofiler插件
MAT,Jprofiler作用:分析Dump内存文件,快速定位内存泄露;获得堆中的数据;

十二、Jprofiler的使用

  1. 假设现在有一个会报出OOM的错误代码如下,且在写代码时不知道抛出的时异常还是错误,而我们一般写的时异常,所以无法捕获到Error
    在这里插入图片描述

  2. 为了测试,手动配置堆大小VM options:

-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

其中:
-Xms:设置初始化内存分配大小,默认为1/64
-Xmx:设置最大分配内存,默认 1/4
-XX:+PrintGCDetails 打印GC拉圾回收信息
-XX :+HeapDumpOnOutOfMemoryError
在这里插入图片描述

  1. 运行结果
    在这里插入图片描述

  2. 找到该项目工程下的hprof文件,并且双击打开
    在这里插入图片描述

  3. 首先看Biggest Objects,发现ArrayList占用了87%的堆,说明问题出在ArrayList上
    在这里插入图片描述

  4. 其次接着看线程,确定问题出在哪一个线程,并且看到问题出在第21行
    在这里插入图片描述

十三、GC

  1. GC一般在堆中进行
  2. GC分为轻量型和重量型
  3. GC大部分回收都在新生区里面的伊甸园区

十四、GC常用算法

1. 引用计数法

给每个堆中的对象设置一个计数器,每使用一次该对象,计数器加一,清楚计数为0的

2. 复制算法

在这里插入图片描述

3. 标记清除算法

在这里插入图片描述

部分资料参考B站狂神说Java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃凉拌辣芒果

不断学习,不断进步,共勉~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值