类的生命周期:

  1. 加载:.class文件(二进制数据)——>读取到内存——>数据放进方法区——>堆中创建对应Class对象——>并提供访问方法区的接口

  2. 验证、准备、解析:

    1. 验证主要是用来检查class文件格式是否正确

    2. 准备阶段:为类变量分配内存

      public static int test = 100; //准备阶段,test=0; public int test2 = 100;

      public static final int test3 = 100; //准备阶段,test3=100

    3. 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,一般不关注。

  3. 初始化:到了初始化阶段,用户定义的 Java 程序代码才真正开始执行。

    Java程序对类的使用方式可分为两种:主动使用与被动使用。一般来说只有当对类的首次主动使用的时候才会导致类的初始化,所以主动使用又叫做类加载过程中“初始化”开始的时机。

    类的主动使用包括以下六种:

    1. 创建类的实例,也就是new的方式
    2. 访问某个类或接口的静态变量,或者对该静态变量赋值(被final修饰除外,会放入常量池)
    3. 调用类的静态方法
    4. 反射(如 Class.forName(“java.lang.String”))
    5. 初始化某个类的子类,则其父类也会被初始化
    6. Java虚拟机启动时被标明为启动类的类,还有就是Main方法的类会首先被初始化

    最后注意一点对于静态字段,只有直接定义这个字段的类才会被初始化(执行静态代码块)。

类加载器

双亲委派模型:

双亲委派机制:

  1. 当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成;
  2. 当 ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成;
  3. 如果 BootStrapClassLoader加载失败(例如在 $JAVA_HOME/jre/lib里未查找到该class), 会使用 ExtClassLoader来尝试加载;
  4. 若ExtClassLoader也加载失败,则会使用 AppClassLoader来加载,如果 AppClassLoader也加载失败,则会报出异常 ClassNotFoundException。

类层次关系

自定义一个类加载器:

@Data
public class MyClassloader extends ClassLoader {private String root;protected Class<?> findClass(String name) throws ClassNotFoundException {byte[] classData = loadClassData(name);if (classData == null) {throw new ClassNotFoundException();} else {return defineClass(name, classData, 0, classData.length);}}/*** 获取类的二进制数据** @param className* @return*/private byte[] loadClassData(String className) {String fileName = root + File.separatorChar+ className.replace('.', File.separatorChar) + ".class";try {InputStream ins = new FileInputStream(fileName);ByteArrayOutputStream baos = new ByteArrayOutputStream();int bufferSize = 1024;byte[] buffer = new byte[bufferSize];int length = 0;while ((length = ins.read(buffer)) != -1) {baos.write(buffer, 0, length);}return baos.toByteArray();} catch (IOException e) {e.printStackTrace();}return null;}public static void main(String[] args) throws Exception {MyClassloader classLoader = new MyClassloader();classLoader.setRoot("C:\\Users\\Administrator\\Desktop\\javhl\\app-starter\\target\\classes");Class<?> testClass = null;
//            testClass = classLoader.loadClass("com.javhl.course.clazzloader.FatherSonClassTest");testClass = classLoader.findClass("com.javhl.course.clazzloader.FatherSonClassTest");Object object = testClass.newInstance();System.out.println(object.getClass().getClassLoader());}
}

JDK8之后的内存区域

内存结构图

元空间(Metaspace):

  1. 从JDK8开始,永久代(PermGen)的概念被废弃掉了,取而代之的是一个称为Metaspace的存储空间。Metaspace使用的是本地内存,而不是堆内存,也就是说在默认情况下Metaspace的大小只与本地内存大小有关。当然你也可以通过以下的几个参数对Metaspace进行控制:
  2. -XX:MetaspaceSize=N:这个参数是初始化的Metaspace大小,该值越大触发Metaspace GC的时机就越晚。随着GC的到来,虚拟机会根据实际情况调控Metaspace的大小,可能增加上线也可能降低。在默认情况下,这个值大小根据不同的平台在12M到20M浮动。使用java - XX:+PrintFlagsInitial命令查看本机的初始化参数,-XX:Metaspacesize为21810376B(大约20.8M)。
  3. -XX:MaxMetaspaceSize=N:这个参数用于限制Metaspace增长的上限,防止因为某些情况导致Metaspace无限的使用本地内存,影响到其他程序。在本机上该参数的默认值为4294967295B(大约4096MB)。
  4. -XX:MinMetaspaceFreeRatio=N:当进行过Metaspace GC之后,会计算当前Metaspace的空闲空间比,如果空闲比小于这个参数,那么虚拟机将增长Metaspace的大小。在本机该参数的默认值为40,也就是40%。设置该参数可以控制Metaspace的增长的速度,太小的值会导致Metaspace增长的缓慢,Metaspace的使用逐渐趋于饱和,可能会影响之后类的加载。而太大的值会导致Metaspace增长的过快,浪费内存。
  5. -XX:MaxMetasaceFreeRatio=N:当进行过Metaspace GC之后, 会计算当前Metaspace的空闲空间比,如果空闲比大于这个参数,那么虚拟机会释放Metaspace的部分空间。在本机该参数的默认值为70,也就是70%。

哪部分内存区域需要回收?

  1. 程序计数器、虚拟机栈、本地方法栈是线程私有的,随线程而生;随线程而灭。栈中的栈帧随着方法的进入和退出执行出栈和入栈操作,每一个栈帧分配多少内存基本上是在类结构确定下来时就已经是已知的; 因此,这几个区域的分配和回收都具备确定性。方法结束或者线程结束时,内存自然就跟着回收了。
  2. 而Java堆和方法区则不一样,一个接口中多个实现类需要的内存可能不一样,一个方法中多个分支需要的内存也可能不一样,只有在程序运行期间才知道创建哪些对象,这部分内存的分配和回收都是动态的。垃圾收集器关注的是这部分内存。

引用计数法(无法解决循环引用问题)

可达性分析算法

Java引用类型:

  1. 强引用。Java中默认声明的就是强引用,比如:只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null,这样一来,JVM就可以适时的回收对象了

    Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收obj = null; //手动置null
    
  2. 软引用( java.lang.ref.SoftReference )。软引用是用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。

  3. 弱引用(java.lang.ref.WeakReference )。弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。如:JDK中的ThreadLocalMap的Key就是弱引用。

  4. 虚引用( java.lang.ref.PhantomReference)。虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收。虚引用必须和引用队列(ReferenceQueue)一起使用。当垃圾回收器准备回收一个对象时,如果发现它还有引用,那么就会在回收对象之前,把这个引用加入到与之关联的引用队列中去。程序可以通过判断引用队列中是否已经加入了引用,来判断被引用的对象是否将要被垃圾回收,这样就可以在对象被回收之前采取一些必要的措施。

jvm垃圾回收之类加载机制相关推荐

  1. jvm gc垃圾回收机制和参数说明amp;amp;Java JVM 垃圾回收(GC 在什么时候,对什么东西,做了什么事情)

    jvm gc(垃圾回收机制) Java JVM  垃圾回收(GC 在什么时候,对什么东西,做了什么事情) 前言:(先大概了解一下整个过程) 作者:知乎用户 链接:https://www.zhihu.c ...

  2. JVM内存区域(Java内存区域)、JVM垃圾回收机制(GC)初探

    一.JVM内存区域(Java内存区域) 首先区分一下JVM内存区域(Java内存区域)和Java内存模型(JMM)的概念.Java线程之间的通信采用的是共享内存模型,这里提到的共享内存模型指的就是Ja ...

  3. JVM架构、JVM垃圾回收机制、垃圾回收算法、垃圾回收器、JMM(内存模型)

    0 JVM和Java的关系 JDK = JRE + Java开发工具(java,javac,javadoc,javap-) JRE = JVM + Java核心类库 即: JDK = JVM + Ja ...

  4. 学习笔记:Java虚拟机——JVM内存结构、垃圾回收、类加载与字节码技术

    学习视频来源:https://www.bilibili.com/video/BV1yE411Z7AP Java类加载机制与ClassLoader详解推荐文章:https://yichun.blog.c ...

  5. 【JVM】JVM垃圾回收机制GC

    文章目录 JVM垃圾回收机制 一.堆内存区域划分 1.1内存分配策略 1.2永久代(Permanent Generation) 1.3元空间(MetaSpace) 二.标记算法 2.1引用计数算法 2 ...

  6. 【深入理解JVM 七】JVM垃圾回收机制

    前边几篇Blog分别介绍了JVM的类加载机制.运行时数据区域,字节码的执行,在执行完成后程序发挥完了自己的作用,线程独有的程序计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭,而线程共享的堆 ...

  7. 4、JVM垃圾回收机制、新生代的GC、GC(Minor GC、FullGC)、GC日志、JVM参数选项、元空间(笔记)

    4.JVM垃圾回收机制 4.1.新生代的GC 4.1.1.串行GC(SerialGC) 4.1.2.并行回收GC(Parallel Scavenge) 4.1.3.并行GC(ParNew) 4.2.G ...

  8. jvm垃圾回收机制_JVM 垃圾回收机制之堆的分代回收

    JVM垃圾回收机制之堆的分代回收 前言 前文我们了解了Java的GC机制,对于堆中的对象,JVM采用引用计数和可达性分析两种算法来标记对象是否可以清除,本文中我们还会了解到JVM将对分成了不同的区域, ...

  9. 垃圾回收机制和JVM垃圾回收常见算法

    垃圾回收机制和JVM垃圾回收常见算法 垃圾回收的好处和特点: 好处: 1. 提高编程效率: 2. 垃圾回收机制保护程序的完整性. 特点: 1. 只能回收无用对象的内存空间,对其他物理资源无能为力: 2 ...

最新文章

  1. cvtcolor python opencv_二值分析 | OpenCV + skimage如何提取中心线
  2. springboot security 权限校验_十二、SpringBoot 优雅的集成Spring Security
  3. linux rsync 安装教程,linux下的rsync配置和使用教程
  4. 2022年中国餐饮经营参数蓝皮书
  5. 恒大汽车:仍在就出售新能源汽车生活项目等资产进行磋商
  6. centos7 docker端口_使用Docker部署Python应用
  7. 服务器上装的hadoop系统,在Ubuntu Server 18.04.1中安装Hadoop系统环境
  8. matlab中的取整函数(ceil、floor、round)
  9. python培训 马哥python班
  10. 【自制线系列】Schneider HMI 与 PLC 通信线制作教程
  11. 为什么闹钟设置了却不响_手机闹钟不响是怎么回事 怎么设置闹钟【图文】
  12. python 相似形态 股票_比对相似k线软件 python比对股市k线相似性
  13. 多线程编程(3):线程池ThreadPool
  14. C语言确定某年星期六,c语言 怎么算某年某月某日是星期几啊?
  15. 强大的nginx反向代理异步传输模式(原理)
  16. matplotlib绘制图例
  17. 新浪微博僵粉(机器粉)识别方法
  18. 苹果公布Apple Watch手表新专利,可穿戴设备少不了Find My技术
  19. 编写js代码的注意问题
  20. 为什么scanf 函数中不能加\n

热门文章

  1. 微软360游戏机改服务器,战斗民族就是干高玩将Xbox 360改装成PC简直改装达人
  2. 小齐读者拿到快手、百度、网易等 offer 的独门秘籍!
  3. 让sublime text显示空格,到底是点还是横杠TabError: inconsistent use of tabs and spaces in indentation
  4. RT-Thread 简介 https://www.rt-thread.org/
  5. IDEA使用git提交代码时,点了commit之后卡死在performing code analysis部分,或者performing code analysis结束后没有进入下一步操作。
  6. matlab可视化大学物理学_传输矩阵法在大学物理波动光学教学中的应用
  7. 三星电子时隔近3年再次成为全球最大半导体厂商
  8. 比亚迪:华为的手机,我们造的
  9. 月球好忙 蓝色起源2024年要将首位女性送上月球表面
  10. 刚嘲讽过iPhone 12,三星就打算“抄”了:取消赠送充电头和耳机?