java_JVM

JVM 探究

  1. 请你谈谈你对JVM 虚拟机的理解
  2. java8 虚拟机和之前的变化更新
  3. 什么是OOM,什么是栈溢出StackOverFlowError?,怎么分析?
  4. JVM 常用调优参数有哪些?
  5. 内存快照如何抓取,怎么分析Dump文件?知道吗?
  6. 谈谈JVM 中内加载器的认识? rt-jar,ext ,application

1.JVM的位置
建立在操作系统之上在这里插入图片描述
2.JVM的体系结构(自己画一遍)
在这里插入图片描述
在这里插入图片描述
垃圾回收的位置
在这里插入图片描述

3.类加载器
作用: 加载class 文件,如 new Student();->有一个类叫student,而这个类是抽象的,new 玩他他就变成具体的实例了,他的引用在栈里面,具体的人在堆里面
例子:
在这里插入图片描述

  1. 虚拟机自带的加载器
  2. 启动类(根)加载器
  3. 扩展类加载器
  4. 应用程序(系统类)加载器
    一直向上找
  5. 百度:双亲委派机制
package com.kuang.reflection;

public class Car {

    public int age;
    public static void main(String[] args) {
        //类是模板,对象是具体的
        Car car1 = new Car();
        Car car2 = new Car();
        Car car3 = new Car();
        car1.age=1;
        car2.age=2;
        car3.age=3;

        System.out.println(car1.hashCode());
        System.out.println(car2.hashCode());
        System.out.println(car3.hashCode());


        Class<? extends Car> aClass1 = car1.getClass();
        Class<? extends Car> aClass2 = car2.getClass();
        Class<? extends Car> aClass3 = car3.getClass();
        System.out.println(aClass1.hashCode());
        System.out.println(aClass2.hashCode());
        System.out.println(aClass3.hashCode());
        ClassLoader classLoader = aClass1.getClassLoader();//AppClassLoader
        ClassLoader parent = classLoader.getParent();//ExtClassLoad -> 扩展类加载器
        System.out.println(classLoader);
        System.out.println(parent);
        System.out.println(parent.getParent());//根加载器 //null  1.不存在,2.java 程序获取不到
    }
}
输出结果:
1163157884
1956725890
356573597
460141958
460141958
460141958
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@677327b6
null

这个String 的toString 方法不会执行

public class String {

    //双亲委派机制: 安全
    //1.APP-->EXC --BOOT (向上查找,最终找到根加载器包下的String类)

    public String toString(){
        return "Hello";
    }

    public static void main(String[] args) {
        String s = new String();
        s.toString();
    }

4.双亲委派机制
1.类加载器收到类加载的请求 Application
2.将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
3.启动加载器检查是否能够加载当前这个类,能加载直到结束,使用当前的加载器,否则抛出异常,通知子加载器进项加载
4.重复步骤3
Class not found
null : java 调用不到,或者不存在,调用不到了java 底层是C++ 写的
Java =C+±- 去掉繁琐的东西,指正,内存管理

}
输出结果:
错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application

  1. 线程级别的东西java 能处理吗,用接口调用本地方法,调用本地方法的修饰符即为native
  2. 在这里插入图片描述

5.沙箱安全机制
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
比如核心类:默认 java,javax 包下面的文件,字节码效验器是不会效验的
双亲委派机制:

  1. 防止恶意代码去干涉善意的代码;
  2. 他守护了被信任的类库边界
  3. 他将代码归入保护域,确定了代码可以进行哪些操作

6.Native
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210529172513679.png
1.本地方法接口调用本地方法库,扩展方法的使用。
在这里插入图片描述

package com.kuang;

public class Demo {

    public static void main(String[] args) {
        new Thread(()->{
        },"my thread name").start();

    }

    //native :凡是带了native 关键字的,说明java 的作用范围达不到了,回去调用底层C语言的库!
    //会进入本地方法栈,
    //调用本地方法接口,JNI
    //JNI 的作用:扩展java 类的使用,融合不同的编程语言为java 所用,最初:C,C++。
    //Java 单生的时候C,C++ 横行,想要立足,必须要有调用C,C++ 的程序
    //他在内存去区域中专门开辟了一块标记区域:Native Method STACK ,登记native 方法
    //在最终执行的时候,加载本地方哭中的方法通过JNI

    //Java 程序驱动打印机,管理系统,RootBoot  常务即可,在企业级应用中较为少见!
    private native void hell0();
    //1跨语言获取数据(http,restful,rpc)
    //调用其他接口: Socket,WebService,Http ~
    //球球爱心网,---> 输入(PHP)-->NodeJS -->Socket  -- C++ 游戏刷爱心

}

JNI 就是本地方法

7.PC寄存器
在这里插入图片描述1. 每次读取下一条指令的时候,计数器就会加1,内存占比非常的小,他是线程私有的
8.方法区
在这里插入图片描述
例子如下:
在这里插入图片描述

  1. Jvm 组成,栈,堆,方法区,
  2. new 一个类的时候,他这里会有一个模板(Test.Class,a,name),右边还有一个常量池(qinjiang),
  3. 你要把对象(new Test()) 放出来的时候,引用放在栈中,真实的地址放在堆中,然后用引用去指向真实的对象,

9.栈
(喝多了吐就栈,吃多了拉就是队列)
1.栈:数据结构
程序=数据结构+算法:持续学习
程序=框架+业务逻辑~:淘汰!
栈:先进后出,后进先出:桶
在这里插入图片描述
1先进,2再进,2先出,1 再出(桶模型)

队列:先进先出(排队嘛)(FIFO:First Input First OutPut)

在这里插入图片描述
2先进,1再进,2先出,1 再出

  1. 为什么main 方法先执行?
    在这里插入图片描述
  2. test 运行完了就弹出栈,然后main 方法弹出栈;
  3. 递归一栈肯定会满了,如下,最终导致栈溢出在这里插入图片描述

栈:栈内存,主管程序的运行,生命周期和线程同步;
线程结束,栈内存也就释放了,对于栈来说,不存在垃圾回收问题
一旦线程结束,栈就Over!

栈:8大基本类型+对象引用+实例的方法;
栈运行原理:栈 帧
在这里插入图片描述
栈满了:Exception in thread “main” java.lang.StackOverflowError
Error错误是严重的,只能让虚拟机停下来,异常还是可以捕获的,可以处理的。
栈+ 堆+ 方法区:交互关系
java 的本质是值快递
在这里插入图片描述
1.画出一个对象实例化的过程在内存中:百度,看视频

10.三种JVM

  1. Sun 公司下的 HotSpot
  2. BEA jRockot
  3. IBM j9 VM
  4. 查看虚拟机用的哪个虚拟机java -version
    11.堆
    1.Heap,一个JVM 只有一个堆内存,堆内存的大小是可以调节的
    在这里插入图片描述
    public static void main(String[] args) {
    new Test().test();
    }
    args 传参。
    类加载读取类文件后,一般把什么东西放到堆中?类,方法,常量,变量,保存我们所有引用类型的真实对象。
    实对象:
    堆内存还要细分位三个区域:
  • 新生区(伊甸园去) young/New

  • 养老区 old

  • 永久区 perm

  • 在这里插入图片描述

  • GC 垃圾回收 ,主要是在伊甸园去和养老区-

  • 假设内存满了,就会OOM 堆内存不够!java Heap space ,例子如下:
    在这里插入图片描述

JDK 8以后,永久存储区改了个名字(元空间)
新生区

  1. 类:诞生和成长的地方,甚至死亡;
  2. 伊甸园区,所有的对象都生成在伊甸园区,new 出来了(如果生成了10个对象,满了,则会轻GC),如果只有一个活的则会进去幸存区
    其他的9个则清空,则剩下的又有10个空间,假如之后幸存0区也满了,假如新生区都满了,则会触发一条重GC,幸存区0 区和1区的能活 下来的则进入养老区,如果养老区重GC Full Gc 10次也满了,即堆内存和养老区满了,则OOM 了,堆溢出。
    在这里插入图片描述
    真理:经过研究,99% 的对象都是临时对象!

12.新生代,老年代
13.永久区
不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小:
 -XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
  -XX:MaxMetaspaceSize,最大空间,默认是没有限制的。

除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:
  -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
  -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

现在我们在 JDK 8下重新运行一下代码段 4,不过这次不再指定 PermSize 和 MaxPermSize。而是指定 MetaSpaceSize 和 MaxMetaSpaceSize的大小。输出结果如下:

这个区域常驻内存的,用来存放JDK 自身携带的Class 对象inteface 元数据存储的是java 运行时的一些环境或类信息·,这个区域不存在垃圾回收!关闭JVM 虚拟机就会释放。这个区域的内存。而且出现oom 跟永久代没什么关系。

一个启动类,加载大量的第三方jar 包,tomcat部署了太多应用,或者大量动态生成的反射类,不断的被加载,知道内存满了就会出现oom

  1. jdk1.6 之前 :永久代,常量池在方法区中。
  2. jdk1.7 :永久代,但是慢慢退化了,去永久代,常量池在堆中。
  3. jdk1.8 之后:无永久代,常量池在元空间。
    在这里插入图片描述
    在这里插入图片描述
    空白最小快:常量池
    我们查看选如何设置内存初始化大小:
    代码如下:
package com.kuang;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

public class Demo02 {

    public static void main(String[] args) {
        //返回虚拟机试图使用的最大内存
        long max = Runtime.getRuntime().maxMemory();//字节1024*1024
        //返回jvm 的初始化总内存
        long total =Runtime.getRuntime().totalMemory();

        System.out.println("max="+max+"字节\t"+max/(double)1024/1024+"MB");
        System.out.println("total="+max+"字节\t"+(total/(double)1024/1024)+"MB");
         //7.7
        //4/1
        //64/1

        //默认情况下:分配的总内存是电脑内存的1/4,而初始化内存: 1/64
       //-Xms1024m -Xmx1024m -XX:+PrintGCDetails
        //新生代 + 老年代 =
        //305664K +699392K =1005056 =981.5M
        //OOM:
             //1.先扩大堆内存看结果 -Xms1024m -Xmx1024m -XX:+PrintGCDetails
            //2.如果还是不行分析下哪个地方出现了问题(专业工具)

    }
}

输出结果
max=1029177344字节 981.5MB
total=1029177344字节 981.5MB
Heap
PSYoungGen total 305664K, used 20971K [0x00000000eab00000, 0x0000000100000000, 0x0000000100000000)
eden space 262144K, 8% used [0x00000000eab00000,0x00000000ebf7afb8,0x00000000fab00000)
from space 43520K, 0% used [0x00000000fd580000,0x00000000fd580000,0x0000000100000000)
to space 43520K, 0% used [0x00000000fab00000,0x00000000fab00000,0x00000000fd580000)
ParOldGen total 699392K, used 0K [0x00000000c0000000, 0x00000000eab00000, 0x00000000eab00000)
object space 699392K, 0% used [0x00000000c0000000,0x00000000c0000000,0x00000000eab00000)
Metaspace used 3197K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 353K, capacity 388K, committed 512K, reserved 1048576K

Process finished with exit code 0

设置参数:
在这里插入图片描述
元空间:逻辑上存在,物理上不存在

如果将初始化和最大内存设置8m

package com.UdpClientDemo01;


import java.util.Random;

//-Xms 8m -Xmx8m -XX:+PrintGCDetails
public class psvm {


    public static void main(String[] args) {
        String str ="kuangshensayjava";
        while(true){
            str+=str+new Random().nextInt(8888888)+new Random().nextInt(999999999);
        }
    }
}

输出结果:

[GC (Allocation Failure) [PSYoungGen: 1536K->488K(2048K)] 1536K->668K(7680K), 0.0020638 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1803K->499K(2048K)] 1983K->906K(7680K), 0.0062892 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 2017K->503K(2048K)] 2424K->1038K(7680K), 0.0014230 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1773K->288K(2048K)] 3300K->2310K(7680K), 0.0033247 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1806K->416K(2048K)] 6804K->5414K(7680K), 0.0007959 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) --[PSYoungGen: 1407K->1407K(2048K)] 6406K->6406K(7680K), 0.0008676 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 1407K->0K(2048K)] [ParOldGen: 4998K->2751K(5632K)] 6406K->2751K(7680K), [Metaspace: 3125K->3125K(1056768K)], 0.0034894 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 15K->0K(2048K)] 4750K->4735K(7680K), 0.0004872 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] 4735K->4735K(7680K), 0.0003136 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] [ParOldGen: 4735K->3587K(5632K)] 4735K->3587K(7680K), [Metaspace: 3125K->3125K(1056768K)], 0.0046072 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] 3587K->3587K(7680K), 0.0008857 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] [ParOldGen: 3587K->3570K(5632K)] 3587K->3570K(7680K), [Metaspace: 3125K->3125K(1056768K)], 0.0066249 secs] [Times: user=0.00 sys=0.03, real=0.01 secs] 
Heap
 PSYoungGen      total 2048K, used 92K [0x00000000ffd80000, 0x0000000100000000, 0x0000000100000000)
  eden space 1536K, 5% used [0x00000000ffd80000,0x00000000ffd97040,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 ParOldGen       total 5632K, used 3570K [0x00000000ff800000, 0x00000000ffd80000, 0x00000000ffd80000)
  object space 5632K, 63% used [0x00000000ff800000,0x00000000ffb7c930,0x00000000ffd80000)
 Metaspace       used 3158K, capacity 4556K, committed 4864K, reserved 1056768K
  class space    used 336K, capacity 392K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3332)
	at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137)
	at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121)
	at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:647)
	at java.lang.StringBuilder.append(StringBuilder.java:208)
	at com.UdpClientDemo01.psvm.main(psvm.java:13)
Disconnected from the target VM, address: '127.0.0.1:57832', transport: 'socket'

14.堆内存调优

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

1.能够看到代码第几行出错:内存快照分析工具,MAT,Jprofile
2.Dubug,一行行分析代码!
MAT,Jprofile 作用:

  1. 分析Dump 内存文件,快读定位内存泄漏
  2. 获取堆中数据
  3. 获取大的对象
package com.kuang;

import java.util.ArrayList;
//Dump文件 -Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
//-Xms 设置初始化内存分配大小 1/64
//-Xmx 这是最大分配内存,默认1/4
//-XX:+PrintGcDetails //打印GC 垃圾回收信息
public class Demo3 {

    //1M
    byte [] array = new byte[1*1024*1024];

    public static void main(String[] args) {
        ArrayList<Demo3> list = new ArrayList<>();
        int count =0;
        try {
            while(true){
                list.add(new Demo3());//第 15 行
                count=count+1;
            }
        } catch (Exception e) {
            System.out.println("count:"+count);
            e.printStackTrace();
        }
        //顶级异常
        //Throwable
           //Exception
          //error

    }


}
//安装插件后会自动导出Dump 文件
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid16300.hprof ...
Heap dump file created [7746509 bytes in 0.024 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at com.kuang.Demo3.<init>(Demo3.java:8)
	at com.kuang.Demo3.main(Demo3.java:15)

Process finished with exit code 1

在这里插入图片描述

15.GC
1.常用算法
16.JMM
17.总结

1.百度
2.思维导图

单点登录- |sso

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值