51 java.lang.Class/java.lang.ClassLoader/InstanceKlass/ClassloaderData 的卸载

news2024/10/7 16:10:40

前言

之前 碰到了一个 flink 基于 ChildFirstClassLoader 来进行任务隔离 导致的内存泄漏的问题 

然后 使用 demo 复现了一下 问题 

之后 想探索一下 java language 中 类型的卸载相关 

并且会 拓展一些其他的知识 

以下测试用例基于 jdk8, 部分截图基于 jdk9 

测试用例

Test29MultiLoaderContextInvoker 驱动类 

/**
 * Test29MultiLoaderContextInvoker
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2021-12-19 09:31
 */
public class Test29MultiLoaderContextInvoker {

    // Test29MultiLoaderContextInvoker
    // -Xmx10M -XX:+UseSerialGC -XX:+TraceClassLoading
    // -Xmx10M -XX:+UseSerialGC -XX:+TraceClassUnloading
    public static void main(String[] args) throws Exception {

        ClassLoader appClassloader = Test29MultiLoaderContextInvoker.class.getClassLoader();
        String[] alwaysParentPatterns = new String[]{};
        URL[] classpathes = new URL[]{
                new File("/Users/jerry/IdeaProjects/HelloWorld/target/classes").toURI().toURL()
        };
        Consumer<Throwable> throwableConsumer = (ex) -> {
            ex.printStackTrace();
        };

        int loopCount = 20;
        for (int i = 0; i < loopCount; i++) {
            ChildFirstClassLoader classLoader = new ChildFirstClassLoader(classpathes, appClassloader, alwaysParentPatterns, throwableConsumer);
            Class mainClass = classLoader.loadClass("com.hx.test12.Test29MultiLoaderContextMain");
            Method mainMethod = mainClass.getDeclaredMethod("main", int.class, String[].class);
            mainMethod.invoke(null, i, args);
        }

    }

}

Test29MultiLoaderContextMain 业务类

/**
 * Test29MultiLoaderContextInvoker
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2021-12-19 09:31
 */
public class Test29MultiLoaderContextMain {

    // hold 1M
    public static byte[] dummyBytes = new byte[1 * 1024 * 1024];

    // Test29MultiLoaderContextInvoker
    public static void main(int idx, String[] args) throws Exception {
        System.out.println(String.format(" Test29MultiLoaderContextMain.main be invoked, idx : %s, args : %s ", idx, args));
        new Thread(() -> {
            try {
                System.out.println(String.format(" bizThread - %s is started ", idx));
                Thread.sleep(10_000);
                System.out.println(String.format(" bizThread - %s is end ", idx));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

}

执行结果如下 

可以看到 应该是第五次启动了之后, 发生了一次 full gc, 卸载了一部分类型, 然后 后面还是发生了 OOM,  一个 Test29MultiLoaderContextMain.class 会占用 1M 的空间 

6 个占用了 6M, 然后 第七次 invoke 的时候发生了 OOM 

假设我们去掉 Thread.sleep(10_000) 

可以看到的是 20次 invoke 均成功执行了, 这次执行里面 我们发现有对 Test29MultiLoaderContextMain.class 的卸载 

jls 中类型的卸载  

 12.7. Unloading of Classes and Interfacesd 

 可以按到的是 类型卸载的前提是 加载它的 classloader 被gc了 

对应于我们这里, 要想卸载 Test29MultiLoaderContextMain.class 就得保证 加载他的 ChilldFirstClassLoader 被卸载了 

​​​​​​

HotSpotVM 中的类型卸载 

以下运行时截图 基于 jdk9, 调试基于 SerialGC 

这里是 输出 "unloading class com.hx.test12.Test29MultiLoaderContextMain" 打印的地方 

堆栈信息提上来一点, 看到这里有一个 data->is_alive(is_alive_closure) 的判断, 判断的就是 对应的 classloader 是否被 gc 标记(还存活)

当然 这里仅仅是一些标记操作, 真真的 clean 操作是在 gc 之后, 清理掉这些 classloaderData, InstanceKlass 什么的 

java.lang.ClassLoader 的创建和回收

我们这里讨论的是 我们自定义的业务的 ClassLoader 

创建是在 new ChildFirstClassloader 的时候 

回收则是 gc 来处理的 

不可到达 就被回收了 

classLoaderData 的创建和回收 

它的创建是 在 resolve InstanceKlass 的时候, 一个 classloader 对应于一个 classLoaderData, 基于 new 分配 

classLoaderData 的清理是在标记完之后, gc 之后, 进行 delete 的 

InstanceKlass 的创建和回收

注意这里的 new 后面的参数, loader_data, size 

klass 是重写了 operator new, 实际分配的空间是属于 loader_data.metaspace.class_vsm, 是属于我们常说到的 Metaspace[元空间] 

之所以 要提到这个, 是因为 空间的回收和这个是有关系的 

InstanceKlass 的回收, 是 classLoaderData 回收的一部分 

回收 metaspace 之前, 如下, 一切 都很正常 

delete metaspace 之后, 可以看到 相关字段都更新为了 dummy word, 可以大致判断出的是 InstanceKlass 被回收了 

具体填充 dummy word 的地方在这里, 回收 chunk 的地方 

java.lang.Class 的创建和回收

是在创建 InstanceKlass, 初始化的时候 创建的 java.lang.Class 

回收 则是 gc 来处理的 

不可到达, 就被 回收了 

以上几种 分配/回收 模式 

从上面可以看到, 有几种内存的 分配, 回收的方式 

1. 基于 c++ 原生的 new, delete 

2. 基于内存池, 上面的 metaspace, heap 均属于

完 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/77105.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

0行代码拿210万年薪,ChatGPT催生新型「程序员」岗:工作纯靠和AI聊天

梦晨 发自 凹非寺量子位 | 公众号 QbitAI靠玩ChatGPT&#xff0c;还能找到新工作&#xff1f;没错&#xff0c;Riley Goodside&#xff08;后面叫他好面哥&#xff09;4月份开始在网上发布玩GPT-3的心得。最近ChatGPT一波爆火&#xff0c;他不光粉丝涨了一万多&#xff0c;还收…

『 云原生·Docker』Docker中部署Nginx

系列文章目录 本系列主要分为以下六大部分,正在更新中,尽请期待&#xff01; 『 云原生生之门』 『 云原生前置知识』 『 云原生Docker』 『 云原生Kubernetes』 『 云原生KubeSphere』 『 云原生DevOps』 &#x1f6a9;点击关注本专栏 提示&#xff1a;已经更新的或正在更新的…

自动驾驶之MultiPath++论文阅读笔记

预测道路参与者的future behavior. 摘要 将输入由dense image-based encoding改为a sparse encoding of heterogeneous scene elements. 即用polylines(折现)来描述road features和原始的agent state information(例如位置、速度和加速度)。 主要方法是对这些元素进行a conte…

【POJ No. 2778】DNA 序列 DNA Sequence

【POJ No. 2778】DNA 序列 DNA Sequence 北大OJ 题目地址 【题意】 DNA序列是一个只包含A、C、T和G的序列。分析DNA序列片段非常有用&#xff0c;若动物的DNA序列包含片段ATC&#xff0c;则意味着该动物可能患有遗传病。 给定m 个遗传病片段&#xff0c;求有多少种长度为n 的…

自动驾驶两大路线对决,渐进式玩家为何更容易得人心?

HiEV消息&#xff08;文/长海&#xff09;对自动驾驶赛道而言&#xff0c;2022年的冬天格外冷冽。寒潮袭来&#xff0c;从各家的应变方式看&#xff0c;不同路径的玩家呈现“冰火两重天”&#xff0c;进化的趋势也越来越清晰。 以Waymo为代表、持续研发L4级无人驾驶的跨越式路线…

web课程设计网页规划与设计 :DW旅游主题网页设计——凤阳智慧旅游官方-地方旅游网站模板html源码HTML+CSS+JavaScript

&#x1f468;‍&#x1f393;学生HTML静态网页基础水平制作&#x1f469;‍&#x1f393;&#xff0c;页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码&#xff0c;这是一个不错的旅游网页制作&#xff0c;画面精明&#xff0c;排版整洁&#xff0c;内容…

ONES X 华西证券|以需求全流程管控,洞见金融数据价值

近日&#xff0c;ONES 签约全国一流证券金融服务商——华西证券&#xff0c;助推华西证券构建需求全流程管控体系&#xff0c;保障需求任务的上下游衔接与顺畅流转&#xff0c;做到系统内所有数据透明化、线上化、统一化&#xff0c;提高团队协同效率&#xff0c;打破「部门墙」…

所谓“生活的艺术“, 就是悠闲二字

关于作者 作为陈独秀、胡适、鲁迅的同时代人&#xff0c;林语堂是"五四"新文化运动的参与者&#xff0c;中国现 代著名作家、学者、翻译家、语言学家&#xff0c;新道家代表人物。他清晰地看到了关于中国 传统文化观点的两种极端倾向&#xff0c;一种是把 中国传统文…

R语言VAR模型的不同类型的脉冲响应分析

目录 模型与数据 估算值 预测误差脉冲响应 识别问题 正交脉冲响应 结构脉冲反应 广义脉冲响应 参考文献 最近我们被客户要求撰写关于脉冲响应分析的研究报告&#xff0c;包括一些图形和统计输出。脉冲响应分析是采用向量自回归模型的计量经济学分析中的重要一步。它们的…

火爆出圈的ChatGPT,你也来体验一下吧!

最近网络上流行了一个叫ChatGPT的东西&#xff0c;他到底是什么东西&#xff1f; ChatGPT是人工智能实验室OpenAI发布的一款对话式聊天机器人。他可以解答很多刁钻有难度的问题&#xff0c;一经发布就火遍科技圈。12月4日&#xff0c;马斯克在咨询该聊天机器人关于推特经营的建…

构建高性能内存队列:Disruptor 永远滴神~

我们清楚使用锁的性能比较低&#xff0c;尽量使用无锁设计。接下来就我们来认识下Disruptor。 Disruptor简单使用 先简单介绍下&#xff1a; Disruptor它是一个开源的并发框架&#xff0c;并获得2011 Duke’s程序框架创新奖【Oracle】&#xff0c;能够在无锁的情况下实现网络…

单机存储系统可靠性及相关技术介绍

一、存储系统可靠性的影响因素单机存储系统包括存储硬件和存储软件。存储硬件又包含存储介质、存储控制器、设备固件&#xff1b;存储软件栈层次则更为复杂&#xff0c;以Linux为例包括&#xff1a;存储设备驱动层、 块设备层(Block Layer)、可选的虚拟块设备层(Device Mapper)…

新手使用wvp-pro和zlm的菜鸟说明(手把手教)

对于wvp-pro的使用&#xff0c;很多大佬都是白嫖菜鸟党&#xff0c;很多都第一次使用wvp&#xff0c;甚至第一次接触国标&#xff0c;连国标最基本流程都不清楚。所以写此文档以供各位菜鸟大佬点评指正 看此文档前提&#xff1a; 第一&#xff1a;先看三遍zlm和wvp的wiki&…

【光照感知子场:差分感知融合模块与中间融合策略相结合】

PIAFusion: A progressive infrared and visible image fusion network based on illumination aware 本文提出了一种基于光照感知的渐进式图像融合网络PIAFusion&#xff0c;自适应地保持显著目标的亮度分布和背景的纹理信息。具体而言&#xff0c;我们设计了一个光照感知子网…

【Java基础篇】基础知识易错集锦(一)

在学习的路上&#xff0c;我们只记得学习新的知识&#xff0c;却忽略了一切新知识都是在旧知识的基础上&#xff1b;努力奔跑的过程中&#xff0c;也要记得常回头看看&#xff1b; 题目展示&#xff1a; 解析&#xff1a; abstract是抽象的意思&#xff0c;在java中&#xff0…

【Vue 快速入门】使用vue脚手架创建一个项目

文章目录一、环境检查1.安装node环境2.脚手架配置3.不同版本vue介绍二、创建项目三、脚手架配置解说1.配置解说2.我的第一个vue程序一、环境检查 1.安装node环境 Node.js发布于2009年5月&#xff0c;由Ryan Dahl开发&#xff0c;是一个基于Chrome V8引擎的JavaScript运行环境…

Flutter - AlignmentGeometry :Alignment 和 FractionalOffset

AlignmentGeometry 是一个抽象类&#xff0c;它有两个常用的子类&#xff1a;Alignment和 FractionalOffset Alignment Alignment继承自AlignmentGeometry&#xff0c;表示矩形内的一个点&#xff0c;他有两个属性x、y&#xff0c;分别表示在水平和垂直方向的偏移 上图中 Flu…

阳光保险港交所上市:年营收1200亿 市值超600亿港元

雷递网 雷建平 12月9日阳光保险集团股份有限公司 (简称&#xff1a;“阳光保险”&#xff0c;06963)今日在港交所上市&#xff0c;发行价为每股5.83港元&#xff0c;募资净额为64.195亿港元。若行使超额配股权&#xff0c;阳光保险可额外再募资9.81亿港元。阳光保险发行价为5.8…

软件测试 -- 进阶 7 软件测试环境构建 与 测试数据准备

工欲善其事&#xff0c;必先利其器。-- 《论语卫灵公》 释译&#xff1a;工匠想要工作做好&#xff0c;一定要先让工具锋利。比喻要做好一件事&#xff0c;准备工作非常重要。 1. 为什么要构建测试环境、准备测试数据 提前准备测试所需资源保证测试有效执行保证测试用序执…

ChatGPT新玩法来了,微信聊天机器人

前言 上一篇文章中说了ChatGPT是什么&#xff0c;然后怎么注册使用。 传送门&#xff1a;花了1块钱体验一把最近很火的ChatGPT 但是实际操作下来还是有不少小伙伴跟我一样遇到各种坑。 没有科学上网工具OpenAI的服务在你的国家无法使用&#xff08;最多的问题&#xff09; 注…