JVM-01 类加载过程及源码分析

ClassLoader源码分析 层次结构和类图 ClassLoader层次结构:       UML类图:     sun.misc.Launcher.ExtClassLoader sun.misc.Launcher.AppClassLoader   显式加载类 在代码中显式加载某个类,有三种方法: this.getClass().getClassLoader().loadClass() 阅读详情

一、JVM类加载过程及源码分析

我们通过ide写的java代码,毫无疑问是最终需要加载到JVM来运行的。试想JVM作为跨语言的平台,能同时支持多种编程语言(js、groory、scala…等)的字节码文件运行,那么在字节码文件和JVM之间,必须有一套完备的流程,来将字节码文件转化为JVM内存中的变量信息。
下图,是坊间盛传的JVM类加载过程,今天我们来探一探水深。
在这里插入图片描述

1.1 前言引语

sun.misc.Launcher的方法很简单,静态代码实例了launcher,供getLauncher()方法获取launcher对象。
在这里插入图片描述
但是,当给我们他通过debug打点到launcher()构造方法获取ExtClassLoader、AppClassLoader时,却发现断点进不到46、52行。是思路错了还是断点无效?

于是我又翻了翻 IBM 关于 Java 中 Debug 实现原理的介绍,文章地址如下:https://www.ibm.com/developerworks/cn/java/j-lo-jpda1/
JDI(Java Debug Interface)是三个模块中最高层的接口,在多数的 JDK 中,它是由 Java 语言实现的。
参考 Oracle 的官方文档:https://docs.oracle.com/javase/9/docs/api/jdk.jdi-summary.html
可以知道 jdi 是一个位于 tools.jar 包下的子包,而 tools.jar 也是由 BootStrap 类加载器负责加载的

可以明确,Debug时调用的是lib/tools.jar的包,而此时启动类加载器势必已经完成启动,所以debug无效。

1.2类加载器

类加载器定义:

  • 启动类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的核心类库,比如 rt.jar、charsets.jar等
  • 扩展类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的ext扩展目录中的JAR 类包
  • 应用程序类加载器:负责加载ClassPath路径下的类包,主要就是加载你自己写的类
  • 自定义加载器:负责加载用户自定义路径下的类包
    JVM中默认读取的路径参数:
      class_path = SecuritySupport.getSystemProperty("java.class.path");
      boot_path  = SecuritySupport.getSystemProperty("sun.boot.class.path");
      ext_path   = SecuritySupport.getSystemProperty("java.ext.dirs");

上节了解到,启动类加载器比较神秘,多是由C++来实现的,那我们就先从Luncher着手看看扩展类加载器和应用程序类加载器的结构。

1、首先查看Launcher的结构,内部类有AppClassLoader、ExtClassLoader ,并且这2个内部类都继承了URLClassLoader。下图看URLClassLoader的组织结构,最终继承了ClassLoader类。所以我们需要明确,类加载器之间并没有继承的父子关系,而是ClassLoader中维护了private final ClassLoader parent;字段,用这种方式来标记当前加载器的父加载器。后面在看到双亲委委派机制时,不能搞混了。
在这里插入图片描述在这里插入图片描述
2、Luncher使用的ClassLoader ,是由getAppClassLoader()生成的,所以JVM的加载的类,首先都需要从App加载器开始加载。
Luncher的构造方法,生成 ExtClassLoader 、AppClassLoader。

    private ClassLoader loader;
	public ClassLoader getClassLoader() {
        return this.loader;
    }

    public Launcher() {
        Launcher.ExtClassLoader var1;
        try {
        	//创建ExtClassLoader扩展类加载器对象
            var1 = Launcher.ExtClassLoader.getExtClassLoader();
        } catch (IOException var10) {
            throw new InternalError("Could not create extension class loader", var10);
        }
        try {
        	//将扩展类加载器作为参数,创建AppClassLoader对象
            this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
        } catch (IOException var9) {
            throw new InternalError("Could not create application class loader", var9);
        }
    }

2、AppClassLoader的getAppClassLoader方法,将ExtClassLoader对象 var0传递给超类ClassLoader,并标记ExtClassLoader 扩展类加载器是AppClassLoader应用程序加载器的父加载器。同时ExtClassLoader 在构造时,传入的父加载器参数是null,但实际其父类加载器是启动类加载器,C++实现的所以在java代码中只出现了BootClassPathHolder。

		//var0是前面生成的ExtClassLoader对象
        public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {
            final String var1 = System.getProperty("java.class.path");
            final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1);
            return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() {
                public Launcher.AppClassLoader run() {
                    URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2);
                    //创建AppClassLoader应用类加载器对象
                    return new Launcher.AppClassLoader(var1x, var0);
                }
            });
        }
        
	 private ClassLoader(Void unused, ClassLoader parent) {
	 	//可见在AppClassLoader中,设置了parent为ExtClassLoader 
        this.parent = parent;
    }

1.3 类加载过程及双亲委派机制

类加载的过程中,依次向上委托父类加载器进行加载。这就形成了双亲委派机制。结合loadClass(name)方法和下图看类的加载顺序,就不难理解了。
双亲委派机制简单的说,就是app加载器先向上交由父类加载器进行加载,父类中找不到,再由子类加载器自行加载。
为什么要设计成双亲委派机制?

  • 安全机制,防止核心API库被随意篡改。
  • 避免重复加载:当父类已经加载过该类时,子类加载器不再加载。保证被加载类的唯一性。
    核心图一 类加载过程及双亲委派机制
    核心图一  类加载过程及双亲委派机制
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            //第一步,在已加载的类中查找是否存在
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                	//第二步,通过父加载器去加载,如果当前是app加载器,则去ext扩展类加载器中查找,如果是扩展类加载器,则去查启动类加载器
                    if (parent != null) {
                    	//扩展类加载器没有重写loadClass方法,会再次进入本方法
                        c = parent.loadClass(name, false);
                    } else {
                    	//启动类加载器加载某个类
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                }

                if (c == null) {
                    //第三步,如果还是没有找到类,那就要去磁盘查找文件,将类加载进来
                    long t1 = System.nanoTime();
                    c = findClass(name);
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

	//具体实施查找的方法
    protected Class<?> findClass(final String name) throws ClassNotFoundException {
        final Class<?> result;
        try {
            result = AccessController.doPrivileged(
                new PrivilegedExceptionAction<Class<?>>() {
                    public Class<?> run() throws ClassNotFoundException {
                    	//第四步,将类的全限定名,改写成目录的形式 (将.替换成/)
                        String path = name.replace('.', '/').concat(".class");
                        //第五步,去磁盘目录中查找文件
                        Resource res = ucp.getResource(path, false);
                        if (res != null) {
                            try {
                            	///第六步,将文件转化为内存中的类
                                return defineClass(name, res);
                            } catch (IOException e) {
                                throw new ClassNotFoundException(name, e);
                            }
                        } else {
                            return null;
                        }
                    }
                }, acc);
        } catch (java.security.PrivilegedActionException pae) {
            throw (ClassNotFoundException) pae.getException();
        }
        if (result == null) {
            throw new ClassNotFoundException(name);
        }
        return result;
    }

1.4 类初始化过程

从磁盘中读取字节码文件 —> 转为二进制文件 —> 验证 —> 准备 —> 解析 —> 初始化
这其中多数核心代码,仍然是C++实现,Java代码中看不到太多有效代码,无奈略过。
在这里插入图片描述

    private Class<?> defineClass(String name, Resource res) throws IOException {
        long t0 = System.nanoTime();
        int i = name.lastIndexOf('.');
        URL url = res.getCodeSourceURL();
        if (i != -1) {
            String pkgname = name.substring(0, i);
            // Check if package already loaded.
            Manifest man = res.getManifest();
            definePackageInternal(pkgname, man, url);
        }
        // Now read the class bytes and define the class
        java.nio.ByteBuffer bb = res.getByteBuffer();
        if (bb != null) {
            // Use (direct) ByteBuffer:         
        } else {
            byte[] b = res.getBytes();
            // must read certificates AFTER reading bytes.
            CodeSigner[] signers = res.getCodeSigners();
            CodeSource cs = new CodeSource(url, signers);
            sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
            return defineClass(name, b, 0, b.length, cs);
        }
    }

    protected final Class<?> defineClass(String name, byte[] b, int off, int len,
                                         ProtectionDomain protectionDomain)
        throws ClassFormatError
    {
    	//前期检查
        protectionDomain = preDefineClass(name, protectionDomain);
        String source = defineClassSourceLocation(protectionDomain);
        Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
        postDefineClass(c, protectionDomain);
        return c;
    }

1.4 自定义类加载器

  • 预期:
    在加载类的时候,从自定义的路径中去查找文件。所以在实现自定义加载器时,只需要把原加载器中定义加载文件的路径替换为我们自己的路径即可。
  • 思路:
    从上面核心图一中,我们看到最终在查到磁盘中类文件的方法实际是: findClass(name),而扩展类加载器和APP类加载器,实际都没有去实现,而是在父类URLClassLoader中实现的 findClass(name)方法,所以在自定义加载器中,只要重写下方path的路径即可。
    protected Class<?> findClass(final String name) throws ClassNotFoundException {
        final Class<?> result;
        try {
            result = AccessController.doPrivileged(
                new PrivilegedExceptionAction<Class<?>>() {
                    public Class<?> run() throws ClassNotFoundException {
                    	//查找磁盘文件路径的核心代码
                        String path = name.replace('.', '/').concat(".class");
                        Resource res = ucp.getResource(path, false);
                        if (res != null) {
                            try {
                                return defineClass(name, res);
                            } catch (IOException e) {
                            }
                        }
                    }
                }, acc);
        }
        return result;
    }

自定义加载器的功能在1.5中实现。

1.5 打破双亲委派机制

  • 预期:打破双亲委派的目的,就是在加载某个类时,不去父类中完成类的加载,而是自行实现加载的逻辑。
  • 思路:JVM中的加载器在定义加载类时,实际是继承或重写loadClass()来实现的。正如核心图一中的代码逻辑,我们只要不再使用原有的loadClass()逻辑,自行实现自由的加载逻辑即可。
public class MyClassLoader extends ClassLoader {
    //需要加载的自定义加载路径
    private String classPath;

    //指定路径的构造方法
    public MyClassLoader(String path){
        this.classPath = path;
    }

	//修改路径的自定义加载器
    private byte[] loadByte(String name) throws Exception {
    	//保持和原代码大体一致
        String path = name.replaceAll("\\.", "/");
        FileInputStream fis = new FileInputStream(classPath + "/" + path + ".class");
        int len = fis.available();
        byte[] data = new byte[len];
        fis.read(data);
        fis.close();
        return data;
    }

    @Override
    protected Class<?> findClass(final String name) throws ClassNotFoundException{
        try {
            byte[] data = loadByte(name);
            //找到文件后,继续沿用原有的加载类的方法
            return defineClass(name, data, 0, data.length);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ClassNotFoundException();
        }
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if(name.startsWith("com.asky")){
                        c = findClass(name);
                    }else {
                        c = this.getParent().loadClass(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

    public static void main(String[] args) throws Exception {
        MyClassLoader classLoader = new MyClassLoader("D:/study");
        Class clazz = classLoader.loadClass("com.asky.test");
        Object obj = clazz.newInstance();
        System.out.println(clazz.getClassLoader());
    }
}

在这里插入图片描述

参考文章:https://cloud.tencent.com/developer/article/1590312

JVM源码分析VMThread线程 而安全点的触发工作就是"VMThread"线程来做,并且此线程还会执行需要安全点才能执行的工作,比如:GC垃圾回收、dump 线程堆栈数据 等等需要安全点的操作。 阅读详情

相关推荐

JVM源码分析之堆外内存(直接内存)

1、堆外内存定义 内存对象分配在JVM中堆以外的内存,也可以称为直接内存,这些内存直接受操作系统管理(而不是JVM),这样做的好处是能够在一定程度上减少垃圾回收对应用程序造成的影响。一般我们使用Unsafe和NIO包下ByteBuffer来创建堆外内存。 2、为什么使用堆外内存 1、减少了垃圾回收 使用堆外内存的话,堆外内存是直接受操作系统管理( 而不是虚拟机 )。这样做的结果就是能保持一个较小的堆内内存,以减少垃圾收集对应用的影响。 2、提升复制速度(io效率) 堆内内存由JVM管理,属于“用户态”;而堆

m0_57768035的博客 2524

实战角度分析JVM 源码(十三)

今天从实战角度分析JVM源码,首先: 1、使用 SourceInsight 来查看 OpenJDK 源代码 如何查看可以见一下文档。工具使用的 SourceInsight https://cloud.tencent.com/developer/article/1585224 这个会耗时久点,但是可以关联全部的。 2、应用分析场景、堆外内存默认是多大 如果我们没有通过-XX:MaxDirectMemorySize 来指定最大的堆外内存,那么默认的最大堆外内...

nandao158的博客 1773

别再自己写消息提示了!5分钟用WPF+Material Design打造专业级Snackbar(支持.NET 6)

本文为WPF开发者提供了一份快速集成专业级Snackbar消息提示的实战指南。通过引入MaterialDesignThemes开源库,在.NET 6 WPF项目中,仅需5分钟即可告别传统的MessageBox,实现遵循Material Design规范、动画流畅、支持队列管理的非侵入式Snackbar控件,显著提升应用的用户体验与现代化交互水平。

year5的博客 172

JVM源码解读笔记

第三部分:汇编 在计算机最开始,就是编写0,1组合,这个可以想下编写程序的麻烦程度。所以就有了汇编,一些助记符。当然,在汇编与0、1之间肯定还有一个逻辑来讲汇编最终变成0、1。因为0、1是硬件认识的东西。汇编只是0、1的变现形式,肯定是不能脱离硬件支持的,因为一切操作都是由硬件通过逻辑电路去计算的。 ================...

Feverasa的博客 3936

Vivado IP核综合失败别慌:除了打补丁,这个TCL命令也能救急(以Video Frame Buffer为例)

本文详细解析了Vivado IP核综合失败的排查方法,特别是针对Video Frame Buffer Read IP的常见问题。从补丁安装到深入分析DCP文件生成机制,再到使用强大的TCL命令`foreach ip_in_proj [get_ips] {compile_c [get_ips $ip_in_proj]}`强制重编译,提供了一套完整的解决方案。帮助开发者快速定位并解决IP核综合失败问题,确保项目顺利进行。

weixin_30892889的博客 424

深入理解光流法外推雷达回波

背景介绍 鉴于本人实在太过疲惫和劳累,一些简单的便于理解的废话就不在记录,耗费两天时间研究了一下光流法,本帖用于记录学习过程中源码的难点细节。 使用光流预测的核心有两个利用多张连续回波图像(变分)或者相邻两张回波图(交叉相关,LK等)计算出光流场(速度矢量场),之后利用半拉格朗日方法进行外推。 半拉格朗日方法 三时间步半拉格朗日方法,其核心公式如下 但这个有点难理解,但看一维的图就很好理解 它的核心就是迭代求Am(位移矢量),如果理解困难的话,其实质上就是通过未来迭代(猜)出当前时刻的Am找到过去的假设

weixin_44695861的博客 6035

JVM学习 - 01 -类加载过程

类加载过程 ​ 有这样一个类Test.java, 平常我们在执行Test.java时,整体流程如下 本文主要介绍类加载到jvm的过程, 即classLoader.loadClass(), 而loadClass的详细过程如下 一个类加载到内存中, 要经过如下过程: 加载 >> 连接 >> 初始化 其中 连接 又分三步: 验证 >> 准备 >> 解析 加载 : 将class文件读到内存 验证 : 验证class文件的合法性, 包括文件格式验证、元数据验证、

qq_33790670的博客 400

告别Vysor!用Scrcpy在Mac上无线投屏安卓手机(附魅族16th闪退修复实战)

本文详细介绍了如何在Mac上配置和使用开源投屏工具Scrcpy,实现安卓手机无线投屏的高效解决方案。从基础环境准备到高级功能调优,包括无线连接配置、输入控制增强、多设备管理和性能优化等实用技巧,特别针对魅族16th等机型的闪退问题提供了修复方案,帮助用户彻底告别Vysor等商业软件。

weixin_28712661的博客 395

JVM根据源码深度解析类加载器,以及类加载器的原理(通俗易懂,不懂你捶我)

要了解类的双亲委派机制,我们得先了解一下JVM提供得三种类加载器。以及先了解一下JVM的类加载的过程 一、JVM类加载过程 JVM的加载大家可以看一下下面这张图 1.加载 将我们写的java文件通过编译生成的class对象加载到内存当中 2.验证 验证生成的class文件是否符合JVM字节码文件的规范 3.准备 这一步给类当中的静态变量划分内存,并赋初始值 4.解析 将类的二进制数据中的符号引用替换成直接引用。说明一下:符号引用:符号引用是以一组符号来描述所引用的目标,符号可以是任何的字面形式的字面量,只

qq_42865087的博客 491

Virtuoso ADE Explorer实战技巧:从基础操作到高级仿真

本文深入解析了Virtuoso ADE Explorer在模拟电路仿真中的核心价值与实战技巧。作为Cadence平台的专业工具,它专为高效、系统化的设计空间探索而生,能大幅提升PVT验证、参数扫描和蒙特卡洛分析的效率。文章从基础界面操作、并行仿真管理,到高级的参数扫描、数据报告生成及蒙特卡洛结果深度剖析,提供了全面的避坑指南与工作流优化建议,帮助工程师从重复劳动中解放,专注于电路设计与性能优化。

ios99的博客 899

ZYNQ实战:PS端驱动DMA实现高效数据流转与验证

本文详细介绍了在ZYNQ平台上通过PS端驱动DMA实现高效数据流转的实战方法。从ZYNQ的PS与PL数据交互基础出发,深入解析DMA核心价值,包括硬件平台搭建、Vivado配置、PS端软件架构设计及性能优化技巧,帮助开发者提升数据传输效率与系统性能。

weixin_29192141的博客 436

JVM_虚拟机目录

<font color="red">在人生的道路上,即使一切都失去了,只要一息尚存,你就没有丝毫理由绝望。因为失去的一切,又可能在新的层次上复得</font> [JVM00_面试官对类加载器子系统、运行时数据区、内存分布、执行引擎 你能坚持到第几问?](https://blog.youkuaiyun.com/TZ845195485/article/details/117573479) [JVM01_概述、跨平台原理、分类、三大商业虚拟机](https://blog.youkuaiyun.com/TZ845195485/articl

所得皆惊喜 4万+

槽型光电开关传感器原理图设计,已量产(光电传感器)

在嵌入式设备的位置限位、物料计数等场景中,槽型光电开关是性价比极高的传感器方案 —— 它通过遮挡发射器与接收器之间的光路实现电平切换,电路简单且抗干扰性优于漫反射式光耦。今天分享一个实际项目中落地的槽型光电开关检测电路,从器件选型到逻辑设计都做了简化适配,适合小批量原型或低成本产品的需求。

不脱发的程序猿 719

千锋“王自健”:Java中的JVM源码分析及调优,学这一套就够了

神似王自健的80后Java脱口秀讲师索尔又上新了:《JVM源码分析及调优实战》视频教程! 扫码获取课程学习地址: 助力千万学子追梦,我们从未停止~索尔老师,你也太快了! 本套《JVM源码分析及调优实战》视频教程是继《全网最全ZooKeeper应用与原理分析课程》、《Dubbo+RPC框架入门最全教程》后的又一大杰作。 JVM是整个Java知识体系的核心基础知识,准备面试的程序员必须要充分掌握好JVM相关知识点。 JVM掌握的深度决定了程序员对待技术的态度。可想而知,JVM这堂课的重要性。快..

IT教育任姐姐的博客 754

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

(JVM学习01)从JDK源码级别剖析JVM类加载机制

从JDK源码级别剖析JVM类加载机制

a250029634的博客 198

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

JVM学习笔记 04、类加载与字节码技术

文章目录前言一、类加载1.1、java文件、字节码文件1.2、类加载与字节码技术1.3、原理分析多态原理异常sychronized二、字节码指令2.3、编译器处理(语法糖)2.3.1-2.3.9(精简)2.3.10、方法重写时的桥接方法2.3.11、匿名内部类(底层原理、引用常量值)2.4、类加载阶段2.4.1、加载阶段2.4.2、链接验证准备解析2.4.3、初始化初始化练习(包装类静态属性、懒惰初始化单例)2.5、类加载器2.5.1、启动类加载器2.5.2、扩展类加载器2.5.3、双亲委派模式2.5.4、

每个人都是独一无二的,把握好自己的节奏,跟着自己的心走。 1098

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

01-从JDK源码彻底剖析JVM类加载机制

一、类加载运行全过程 当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把主类加载到 JVM。 通过Java命令执行代码的大体流程如下: 解释一下上图,我们的JAVA程序在启动的时候,首先由java.exe文件启动,底层调用jvm.dll(可以看成是一个JAR包),由c++创建一个JVM, 并且会由c++创建一个引导类加载器(BootstrapLoader),然后调用java代码执行Launcher里面的getLauncher方法,会分别去加载扩展类加载器(ExtClassLo

weixin_43691942的博客 321

【胖虎的逆向之路】01——动态加载和类加载机制详解

本文记录了类加载器和动态加载之间的关系和原理,由于作者能力有限,会尽力的详细讲解两者之间的关系,如本文中有任何错误,烦请指正,感谢~Android中的类加载器机制与JVM一样遵循双亲委派(双亲加载)模式

无方少年游 2621

JVM源码分析系列

JVM源码分析系列 占小狼 3 2019.01.27 10:35:22 字数 363 阅读 4,258 记得关注一下公众号 JVM G1算法系列 G1垃圾收集器介绍 G1垃圾收集器之RSet G1垃圾收集器之SATB G1垃圾收集器之对象分配过程 ZGC系列 ZGC,一个超乎想象的垃圾收集器 ZGC什么时候进行垃圾回收 JVM源码分析系列 深入分析Object.finalize方法的实现原理 JV...

mhHao的博客 660

jvm源码分析之启动过程

这里介绍的是openjdk1.8的源码,分析jvm的启动过程,入口类main.c,入口方法main,动态库文件的加载等,创建过程jni.cpp->thread.cpp的调用过程

qwlhw的博客 759

带你玩转JVM类加载机制原理

当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把主类加载到JVM。将磁盘中存储的字节码文件加载到JVM的过程,使得Java程序能够运行。类加载实例代码。

m0_74020481的博客 121

JVM | 基于openJDK源码深度拆解Java虚拟机

本篇完毕,我们来回顾下:在Java中,一切皆为对象。所以我们从对象出发,探索对象的内存结构。通过其设计的结构关联到JVM虚拟机的其它组件。一步步的解构这个JVM系统,最终掌握完整的JVM虚拟机。

StudyBrainEx 1742

深入理解JVM(1):类加载器

文章目录类加载器1.简介2.Java虚拟机与程序的生命周期3.类的加载、连接与初始化(类加载的最重要的3个阶段)3.1加载3.2连接3.3 初始化4.类的使用和卸载(类加载的剩余两个阶段)5 类记载阶段小结 类加载器 1.简介 在Java代码中,类型的加载、连接与初始化过程都是在程序运行期间完成的。 提供了更大的灵活性,增加了更多的可能性。 要注意理解上面的第一句话,首先类型是什么? 类型:...

超级无敌小胖头 1360

01 类加载机制深度解析

1 从java.exe开始讲透java类加载运行全过程 2 从JDK源码级别剖析JVM核心类加载器 3 从JDK源码级别剖析类加载双亲委派机制 4 手写自定义类加载器打破双亲委派机制 5 Tomcat类加载机制深度剖析 6 手写Tomcat类加载器实现多版本代码共存隔离 ...

g759780748的博客 203
上一篇: 从Guava-Cache到HashMap
下一篇: JVM-02 内存模型及内存分配机制
旧梦昂志
博客等级 码龄7年 3724粉丝 68原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

旧梦昂志

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值