JVM调优篇

JVM理解

jvm学习

JVM生命周期

在这里插入图片描述

JVM架构图

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

类的加器分类

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

1:字节码篇

1.0:字节码工具

1:官方查看字节码工具: javap

2:IDEA查看字节码工具

  1. IDEA下载jclasslib插件,编译java文件
  2. 点击View, 找到 Show Bytecode With Jclasslib

2:类的加载篇

2.0:api

方法描述
getClassLoader()获取加载器
getParent()获取父类加载器
   @Test
    public void test1(){
        // 对于自定义类,使用系统类加载器进行加载
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();   
        System.out.println(classLoader);

        //调用系统类加载器的getParent();获取扩展类加载器
        ClassLoader classLoader1 = classLoader.getParent();
        System.out.println(classLoader1);

        //调用扩展加载器的getParent():无法获取引导类加载器
        // 引导类加载器主要负责加载java的核心类库,无法加载自定义类的。
        ClassLoader classLoader2 = classLoader1.getParent();
        System.out.println(classLoader2);

        //String的加载类是类加载器。
        ClassLoader classLoader3 = String.class.getClassLoader();
        System.out.println(classLoader3);
    }

在这里插入图片描述

2.1:启动类加载器(Bootstrap ClassLoader)

package chapter04.java;
 
import java.net.URL;
 
/**
* 加载器测试
*/
public class ClassLoaderTest {
    public static void main(String[] args) {
        System.out.println("**********启动类加载器**************");
        // 获取 BootstrapClassLoader 能够加载的 api 的路径
        URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs();
        for (URL element : urLs) {
            System.out.println(element.toExternalForm());
        }
        // 从上面的路径中随意选择一个类,来看看他的类加载器是什么:引导类加载器
        ClassLoader classLoader = java.security.Provider.class.getClassLoader();
        System.out.println(classLoader);// null  引导类加载器是获取不到的
    }
}

执行结果

**********启动类加载器**************
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/resources.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/rt.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/sunrsasign.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/jsse.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/jce.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/charsets.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/lib/jfr.jar
file:/D:/ProgramFiles/Java/jdk1.8.0_251/jre/classes
null

2.2:扩展类加载器(Extension ClassLoader)

package chapter04.java;
 
import java.net.URL;
 
/**
* 加载器测试
*/
public class ClassLoaderTest {
    public static void main(String[] args) {
        System.out.println("***********扩展类加载器加载路径*************");
        String extDirs = System.getProperty("java.ext.dirs");
        for (String path : extDirs.split(";")) {
            System.out.println(path);
        }
 
        // 从上面的路径中随意选择一个类,来看看他的类加载器是什么:扩展类加载器
        ClassLoader classLoader1 = sun.security.ec.CurveDB.class.getClassLoader();
        System.out.println(classLoader1); // sun.misc.Launcher$ExtClassLoader@1540e19d
    }
}

执行结果

***********扩展类加载器加载路径*************
D:\ProgramFiles\Java\jdk1.8.0_251\jre\lib\ext
C:\WINDOWS\Sun\Java\lib\ext
sun.misc.Launcher$ExtClassLoader@5cad8086
 

2.3:系统类加载器(AppClassLoader)

通过ClassLoader的getSystemClassLoader() 方法可以获取到该类加载器

2.4:自定义类加载器

  1. 继承ClassLoader类
  2. 重写findclass()方法;
public class MyClassLoader extends ClassLoader {
    private String path;
 
    public MyClassLoader(String path) {
        this.path = path;
    }
 
    public MyClassLoader(String path, ClassLoader parentClassLoader) {
        super(parentClassLoader);
        this.path = path;
    }
 
    /**
     * 重写父类的findClass方法,在ClassLoader在执行 loadClass 方法时,
     * 如果父加载器不会加载类,就会调用当前重写的方法进行加载类
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        BufferedInputStream bis = null;
        ByteArrayOutputStream baos = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(path + name + ".class"));
            baos = new ByteArrayOutputStream();
            int len;
            byte[] data = new byte[1024];
            while ((len = bis.read(data)) != -1) {
                baos.write(data, 0, len);
            }
            //获取内存中的完整的字节数组的数据
            byte[] classByteArray = baos.toByteArray();
            //将字节数组转换为Class的实例
            return defineClass(null, classByteArray, 0, classByteArray.length);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != baos) {
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (null != bis) {
                    bis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

测试:

public class MyClassLoaderTest {
    public static void main(String[] args) throws ClassNotFoundException {
        MyClassLoader myClassLoader = new MyClassLoader("d:/");
        Class<?> aClass = myClassLoader.loadClass("Demo");
        System.out.println("加载此类的类加载器为: " + aClass.getClassLoader());
        System.out.println("加载此类的类加载器的父类加载器为: " + aClass.getClassLoader().getParent().getClass().getName());
    }
}

运行结果:

加载此类的类加载器为: com.wsh.MyClassLoader@2f2c9b19
加载此类的类加载器的父类加载器为: sun.misc.Launcher$AppClassLoader

3:运行时内存篇

3.0:堆内存大小参数

  1. -Xms:初始堆大小
  2. -Xmx:最大堆大小
  3. -XX:NewRatio:设置新生代和老年代的比值。如:为3,表示年轻代与老年代比值为1:3
  4. -XX:PrintGCDetails:查看程序运行GC的运行情况

3.1:内存溢出dump文件分析

4:垃圾回收篇

4.1:垃圾判别算法

  1. 引用技术算法:

给对象添加一个引用计数器,每当对象被引用了,计数器加1,当引用失效之后,计数器减1,当值为0时就是可回收的对象。该方法存在一个循环引用的问题,如下代码

public class Test{
	public static void mian(String[] args){
		ObjectA A=new ObjectA();
		ObjectB B=new ObjectB();
		A=B;
		B=A;
		A=null;
		B=null;
	}
}
在这段代码中,代码执行到B=A该语句时,ObjectA和ObjectB的引用计数均为2,而执行代码结束之后,A和B都置为null,两个对象的计数均减1,但是还存在着A和B之间的相互引用,此时ObjectA和ObjectB的引用计数仍为1,而A和B两个实例又早已不用,终将会进入一种循环状态,导致无法被当成垃圾进行回收。
  1. 可达性分析算法

判断对象与GCRoot是否有引用链,即是否可达,如果对象到GCRoot没有任何引用链,则对象是不可用的,可被当成垃圾进行回收;如果是可达的,则对象不可回收。

如A与GCRoot有相连,B与A相连,C与B相连,这几个对象都是与GCRoot有连接,都是可达对象

而出现一个D不与上述某一对象连接,或者是链接了一个不与GCRoot有连接的对象,则它与GCRoot不可达,是可回收的对象

在这里插入图片描述

5:JVM监控及诊断工具篇

5.0: 命令行篇

  1. jps:查看正在运行的java进程
  2. jmap:dump内存文件
    例如:jmap -dump:live,format=b,file=zhang.hprof pid
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值