类加载器深入剖析

JDK类加载器剖析 我之所以深入研究 Java 类加载器,是为了解决一个奇怪的问题。流行出版物,也就是人们所认为的 Java 世界的灯塔,充斥着关于这个主题的相互矛盾和过时的信息。这种矛盾引发了我的调查 — — 在 Java 类加载器的迷宫中寻求清晰的答案。 作为一名 Java 开发人员,您可能遇到过ClassNotFoundException一些NoClassDefFoundError神秘的消息,它们会暂时中断您的编码流程。旨在阐明这些问题的在线资源往往反而增加了混乱。 阅读详情

java虚拟机与程序的生命周期

在如下的集中情况下,Java虚拟机将结束声明周期:

-执行了System,exit()方法

-程序正常执行结束

-程序在执行的过程中遇到了异常或错误而异常终止

-由于操作系统出现错误而导致Java虚拟机进程终止

类的加载、连接与初始化

加载:查找并加载类的二级制数据

连接:

-验证:确保被加载的类的正确性

-准备:为类的静态变量分配内存,并将其初始化为默认值

-解析:把类中的符号引用转换为直接引用。

初始化:为类的静态变量服务正确的初始值。

Java程序对类的使用方式可以分为两种:

--主动使用

--被动使用

所有的Java虚拟机必须在每个类或者接口被Java程序“首次主动使用”时才初始化他们。

主动使用(六种)

--创建类的实例

--访问某个类或者接口的静态变量,或者对该静态变量赋值

--调用类的静态方法

--反射(如Class.forName("com.zz.Test"))

--初始化一个类的子类

--Java虚拟机启动时被标明为启动类的类(Java Test类或者Main方法)

除了以上六种情况,其他使用Java类的方式都被看做是对类的被动使用,都不会导致类的初始化。

类的加载:

类的加载是指将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。

加载.class文件的方式
–从本地系统中直接加载
–通过网络下载.class文件(URLClassLoader(URL[] urls))
–从zip,jar等归档文件中加载.class文件
–从专有数据库中提取.class文件
–将Java源文件动态编译为.class文件

 

类的加载的最终产品是位于堆区中的class对象

Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。(反射)

类加载器一共有两大类:Java虚拟机自带的加载器和用户自定义的类加载器

java虚拟机自带的类加载器:

•根类加载器(Bootstrap)
•扩展类加载器(Extension)
•系统类加载器(System)

根类加载器:使用C++编写,程序员无法在Java代码中获取该类。根类加载器负责加载虚拟机的核心类库,如java.lang.*等。根类加载器的实现依赖于底层操作系统,属于虚拟机的实现的一部分,它并没有继承java.lang.ClassLoader类。

扩展类加载器:它的父类加载器为根类加载器。加载jre\lib\ext目录下的类库。扩展类加载器是纯Java类,是java.lang.ClassLoader的子类。

系统类加载器也称为应用类加载器,它的父类加载器为扩展类加载器。它从环境变量classPath所指定的目录中加载类,它是用户自定义的类加载器的默认父类加载器。系统类加载器是纯Java类,是java.lang.ClassLoader的子类。

用户自定义的类加载器

用户可以定制类的加载方式,都是java.lang.ClassLoadeer的子类。

疑问:String的类加载器是谁呢???

public class StringClassLoader {
    public static void main(String[] args) {
        try {
            Class<?> name = Class.forName("java.lang.String");
            System.out.println(name.getClassLoader());
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

输出:null

因此String的类加载器是启动类加载器。

类加载器并不需要等到某个类被“首次主动使用”时再加载它:

JVM规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载的过程中遇到了.class文件缺失或存在错误,类加载器必须在程序首次主动使用该类时才报告错误(linkageError错误)

如果这个类一直没有被程序主动使用,那么类加载器就不会报告错误。

 

类被加载后,就进入连接阶段。

连接就是将已经读入到内存的类的二进制数据合并到虚拟机的运行时环境中去。

连接:

类的验证:

 准备:

在准备阶段,Java虚拟机为类的静态变量分配内存,并设置默认的初始值。例如,下面的Sample类,在准备阶段,将为int类型的静态变量a分配4个字节的内存空间,并且赋予默认值0,为long类型的静态变量b分配8个字节的内存空间,并且赋予默认值0.

public class Sample {
    private static int a = 1;
    private static long b;
    static {
        b = 2;
    }
}

解析:

在解析阶段,Java虚拟机会把类的二级制数据中的符号引用替换为直接引用。例如在Worker类中的gotoWork()方法中会引用Car类的run()方法

public void gotoWork() {

    car.run();

}

在Worker类的二进制数据中,包含了一个对Car类run()方法的符号引用,它由run()方法的全名和相关描述符组成。在解析阶段,Java虚拟机会把这个符号引用替换为一个指针,该指针指向Car类的run()方法在方法区内的内存位置,这个指针就是直接引用。

初始化:

 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值。在程序中,静态变量的初始化有两种途径:

(1)在静态变量的声明处进行初始化;

(2)在静态代码块中进行初始化。

例如在上面的Sample例子中a被显式的初始化,而变量b是在静态代码块中初始化的。

静态变量的声明语句以及静态代码块都被看做类的初始化语句,Java虚拟机会按照初始化语句在类文件中的先后顺序来依次执行他们。

 例子:

class Singleton {
    private static Singleton singleton = new Singleton();
    public static int counter1;
    public static int counter2 = 0;

    private Singleton() {
        counter1++;
        counter2++;
    }

    public static Singleton getInstance() {
        return singleton;
    }
}
public class MyTest {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        System.out.println("counter1=" + Singleton.counter1);
        System.out.println("counter2=" + Singleton.counter2);
    }
}

输出:

counter1=1
counter2=0

原因:

准备阶段为静态变量赋值默认值(类型的默认值,不是程序中赋值)此时:singleton = null  counter1=0  counter2=0

初始化阶段,为静态变量按照顺序赋予正确的值:

首先执行singleton = new singleton();会执行构造器,因此counter1=1,counter2 = 1

然后执行counter1和counter2的赋值语句,因此counter1=1 counter2 = 0;

 

初始化步骤:

(1)假如这个类还没有被加载和连接,那就先进行加载和连接。

(2)假如类存在直接的父类,并且这个父类还没有被初始化,那就向初始化直接的父类

(3)假如类中存在初始化语句,那就依次执行这些初始化语句。

例子:

public class FinalTest {
    public static final int x = 8 / 2;
    static {
        System.out.println("FinalTest static block");
    }
}

class Test {
    public static void main(String[] args) {
        System.out.println(FinalTest.x);
    }
}

 输出:

4

原因: 常量在编译期间就会调入类的常量池中 ,所以直接引用final类型的变量,类并没有被初始化 

public class FinalTest2 {
    public static final int y = new Random().nextInt(100);
    static {
        System.out.println("FinalTest2 static block");
    }
}
class Test2 {
    public static void main(String[] args) {
        System.out.println(FinalTest2.y);
    }
}

输出:

why  ?????

原因:x在编译时就可以确定,y只有在运行时才能确定

 

当JAVA虚拟机初始化一个类时,要求它的所有父类都已经被初始化,但是这条规则并不适用于接口

1)在初始化一个类时,并不会先初始化它所实现的接口

2)在初始化一个接口时,并不会先初始化它的父接口

因此,一个父接口并不会因为它的子接口或者实现类的初始化而初始化。只有当程序首次使用特定接口的静态变量时,才会导致该接口的初始化。

class Parent {
    static int a = 3;
    static {
        System.out.println("Parent static block");
    }
}
class Child extends Parent {
    static int b = 4;
    static {
        System.out.println("Child static block");
    }
}
public class Test1 {
    static {
        System.out.println("Test1 static block");
    }

    public static void main(String[] args) {
        System.out.println(Child.b);
    }
}

输出:

如果将main函数调用换成:

 

输出:

程序对子类的“主动使用”会导致父类被初始化;但是父类的“主动”使用并不会导致子类初始化(不可能说生成一个bjectO类的对象就导致系统中所有的子类都会被初始化)

 

只有当程序访问的静态变量或者静态方法确实在当前类或当前接口中定义时,才可以认为是对类或接口的主动使用。

 

调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化

例子:

public class ClassLoaderTest {
    public static void main(String[] args) {
        ClassLoader loader = ClassLoader.getSystemClassLoader();
        try {
            Class<?> aClass1 = loader.loadClass("com.zy.jvm.FinalTest");
            System.out.println("=======================");
            aClass1 = Class.forName("com.zy.jvm.FinalTest");
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
FinalTest是之前定义的一个类:
public class FinalTest2 {
    public static final int y = new Random().nextInt(100);
    static {
        System.out.println("FinalTest2 static block");
    }
}
}

输出为:

 若有一个类加载器能成功加载Sample类,那么这个类加载器被称为定义类加载器,所有能成功返回Class对象的引用的类加载器都被称为初始类加载器。(即定义类加载器及其所有子类加载器都被称为初始类加载器)

父亲委托机制的优点是能够提高软件系统的安全性。因为在此机制下,用户自定义的类加载器不可能加载应该由父类加载器加载的可靠类,从而防止不可靠甚至恶意的代码代替由父加载器加载的可靠代码。例如java,lang.Object类总是由根类加载器加载,其他任何用户自定义的类加载器都不可能加载含有恶意代码的java.lang.Object类。

命名空间:

每个类加载器都有自己的命名空间,命名空间由该加载器及所有父类加载器所加载的类组成。在同一个命名空间,不会出现类的完整名字(包括类的包名)相同的两个类;在不同的命名空间中,有可能会出现类的完整名字相同的两个类。

扩展:是否属于一个类,由包名和加载器决定。

自定义类加载器:

要创建用户自己的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可。

public class MyClassLoader extends ClassLoader{
    private String name; //类加载器的名字
    private String path = "d:\\"; //加载类的路径
    private final String fileType = ".class"; //class文件的扩展名
    public MyClassLoader(String name) {
        super();  //让系统类加载器称为该类加载器的父类加载器
        this.name = name;
    }

    public MyClassLoader(ClassLoader parent, String name) {
        super(parent);   //显式指定该类加载器的父类加载器
        this.name = name;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] date = loadClassDate(name);
        return this.defineClass(name, date, 0, date.length);
    }

    private byte[] loadClassDate(String name) {
        byte[] date = null;
        name = name.replace(".", "\\");
        try (InputStream is = new FileInputStream(new File(path + name + fileType));
             ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()){
            int ch = 0;
            while (-1 != (ch = is.read())) {
                byteArrayOutputStream.write(ch);
            }
            date = byteArrayOutputStream.toByteArray();
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return date;
    }
    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    @Override
    public String toString() {
        return "MyClassLoader{" +
                "name='" + name + '\'' +
                '}';
    }
}

 

class MyClassLoaderTest {
    public static void main(String[] args) {
        MyClassLoader classLoader1 = new MyClassLoader("loader1");
        classLoader1.setPath("d:\\myapp\\serverlib\\");
        MyClassLoader classLoader2 = new MyClassLoader(classLoader1, "loader2");
        classLoader2.setPath("d:\\myapp\\clientlib\\");
        MyClassLoader classLoader3 = new MyClassLoader(null, "loader3");
        classLoader3.setPath("d:\\myapp\\otherlib\\");
        test(classLoader2);
        test(classLoader3);
    }
    public static void test(ClassLoader loader) {
        Class clazz = null;
        try {
            clazz = loader.loadClass("Sample");
            Object instance = clazz.newInstance();
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}

Sample类:

public class Sample {
    private static int a = 1;
    private static long b;
    static {
        b = 2;
    }

    public Sample() {
        System.out.println("Sample is load by: " + this.getClass().getClassLoader());
    }
}

 将class文件放在三个上面定义的目录中,输出为:

 

别再傻傻分不清了!STM32定时器里Prescaler和ClockDivision到底有啥区别? 本文深入解析STM32定时器中Prescaler和ClockDivision的区别与应用场景。Prescaler作为定时器的'心跳调节器',决定计数频率;而ClockDivision则是输入捕获的'抗噪滤镜',有效抑制高频噪声。通过实战案例和示波器实测数据,帮助开发者避免常见配置误区,提升嵌入式系统稳定性。 阅读详情

相关推荐

VXLAN技术详解

VXLAN(虚拟可扩展局域网)是一种Overlay二层虚拟化技术,通过MAC-in-UDP封装在IP网络上构建大规模虚拟二层网络。核心组件包括VTEP(隧道端点)、24位VNI(支持1600万个虚拟网络)和VXLAN网关。相比VLAN,VXLAN具有超大规模扩展、跨三层互联、支持虚拟机无缝迁移等优势,适用于云数据中心多租户隔离、跨数据中心互联等场景。其基于IP路由的封装方式无需改造物理网络,为现代云网络提供了弹性、安全的虚拟化解决方案。

kjkdd的博客 595

详解JAVA类加载器

一文讲明白什么是类加载器、SPI机制、热加载

BugMan的博客 2418

DSSP 工具:蛋白质二级结构信息计算与批量处理教程

DSSP(Dictionary of Secondary Structure in Proteins)是一款经典的蛋白质二级结构计算工具,由荷兰癌症研究所(NKI Research)Perrakis 团队维护。它通过分析蛋白质的 PDB 结构文件,能够自动标注每个氨基酸残基的二级结构类型、相对溶剂可及性(暴露面积)等关键信息,为后续的拓扑图绘制、疏水 / 亲水表面分析、二级结构预测模型训练等提供核心数据支持。

good_rrrrr的博客 1838

什么是类加载器之类加载获取

类加载的获取

weixin_65493827的博客 595

PCIe学习笔记(一)-------1.3 PCIe数据包(TLP,DLLP,PLP)

1,PCIe的层次结构 PICe设备在硬件电路上可以分为三个层次结构:事务层(Transaction Layer)、数据链路层(Data Link Layer)、物理层(Physical)。每一个层次又可以分为两个部分,分别为处理发送和处理接收的部分。 也可以分为四个层次,将事务层以上的层次称为软件层(Software Layer)。 2,PCIe数据包 前面已经说过PCIe之间是以数据包的形式来传输数据的,协议共定义了3类数据包。与处理层相关的是处理层数据包(TLP),与数据链路层相关的是数据

llxxyy507的博客 2万+

keil软件调试(Debug)仿真教程(软件调试和硬件调试的区别)及常用调试按键详解

单片机的调试分为两种,一种是使用软件模拟调试,第二种是硬件调试,两种调试方式各有不同,软件模拟调试有误差,而硬件调试,借用仿真器调试是嵌入式开发中常用方法。

weixin_51624736的博客 3万+

使用自定义类加载器打破双亲委派机制实现自定义String类

今天我和大家如何用自定义加载器打破双亲委派机制。 在介绍双亲委派机制前,我先来聊聊Java里面有几种类加载器。 引导类加载器:Bootstrap classloader 扩展类加载器:ExtClassLoader 应用程序类加载器:AppClassLoader 自定义加载器:MyClassLoader(这个名字自定义的) 接下来我们来介绍下什么是双亲委派机制,如下图所示: 在这里类加载其实就是个双亲委派机制,比如加载某个类时会先委托父加载器寻找目标类,找.

IT枫斗者的博客 1536

RK3588开发板实战:从零开始移植Ubuntu 24.04(讯为SDK版)

本文详细介绍了如何在RK3588开发板上从零开始移植Ubuntu 24.04系统(讯为SDK版),涵盖开发环境准备、SDK解析、根文件系统定制、驱动适配、系统集成与烧录等全流程。通过实战案例,帮助开发者快速掌握RK3588开发板的系统移植技巧,适用于嵌入式开发与定制化Linux系统构建。

sand8的博客 437

类的加载机制双亲委派机制

1、加载:将源文件(代码)编译成.class文件,传递给类加载器 2、验证:类加载器拿到这些字节码文件后开始执行检查(通过本地类库),确保加载进来的字节流格式符合java虚拟机要求 3、准备:对类变量(不是实例变量)分配内存,并且给一个默认初始化的值(0或者null) 4、解析:将常量池中的符号引用加载成直接引用(如string str = new string(“123”),str就是符号引用,123是直接引用) 5、初始化:对类的静态变量初始化为指定的值,执行静态代码块 双亲委派机制:如果一个类加载

m0_69234258的博客 203

YOLOv11改进 | 注意力篇 | YOLOv11引入CA注意力机制

摘要:最近关于移动网络设计的研究已经证明了通道注意力(例如,挤压和激励注意力)对于提升模型性能的显着有效性,但它们通常忽略了位置信息,而位置信息对于生成空间选择性注意力图很重要。到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv11改进有效涨点专栏,本专栏目前为新开的,后期我会根据各种前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~3.2 在Extramodule里创建CA。在CA.py文件里添加给出的CA代码。

tsg6698的博客 2979

【100%通过率】2024华为OD机试真题E卷 C++语言 实现【流浪地球】

流浪地球计划在赤道上均匀部署了N个转向发动机,按位置顺序编号为0~N-1。 1) 初始状态下所有的发动机都是未启动状态; 2) 发动机起动的方式分为“手动启动”和“关联启动”两种方式; 3) 如果在时刻1一个发动机被启动,下一个时刻2与之相邻的两个发动机就会被“关联启动”; 4) 如果准备启动某个发动机时,它已经被启动了,则什么都不用做; 5) 发动机0与发动机N-1是相邻; 地球联合政府准备挑选某些发动机在某些时刻进行“手动启动”,当然最终所有的发动机都会被启动。 哪些发动机最晚被启动呢?

MISAYAONE的博客 4212

关于Java中的类加载器

相信大家都遇到过java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这个异常背后涉及到的是Java技术体系中的类加载机制。其中Java有三种加载器: 1)根类加载器:Bootstrap ClassLoader(我们使用的String等类) 也称为引导类加载器,负责java核心类的加载。比如,System Object String等,在JDK中的JRE的lib目录...

zjgyjd的博客 239

matlab 一维相位解缠

一维相位解缠算法的matlab代码实现。

点云侠的博客 372

深入剖析Tomcat之Bootstrap类与类加载器机制

Bootstrap类作为Tomcat启动入口,通过main方法完成关键初始化工作:设置路径参数、创建多级类加载器(commonLoader、catalinaLoader、sharedLoader)并加载核心Catalina类。Tomcat采用分层类加载机制,commonLoader加载基础通用类,catalinaLoader加载容器核心类,sharedLoader处理共享资源,实现了类资源的安全隔离与高效管理。这种设计既保证了系统稳定性,又为Web应用提供了灵活的类加载环境。

wj_rdk的博客 836

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

21-类加载器实战剖析与疑难点解析

类加载器实战剖析与疑难点解析 1.找到各种类加载所加载class文件的位置: public class MyTest18 { public static void main(String[] args) { System.out.println(System.getProperty("sun.boot.class.path"));//根类加载器 System...

qq_40574305的博客 165

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

类加载器深入解析及重要特性剖析

加载:把二进制形式的java类型读入java虚拟机中 验证 准备:为类变量分配内存,设置默认值。但是在到达初始化之前,类变量都没有初始化为真正的初始值 解析:解析过程就是在类的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用替换成直接引用的过程 初始化:为类变量赋予正确的初始值 类实例化:为新的对象分配内存、为实例变量赋默认值,为实例变量赋正确的初始值,Java编译器为它编译的每一个...

凯凯王的技术生涯 401

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

20-类加载器命名空间实战剖析与透彻理解

类加载器命名空间实战剖析与透彻理解 关于命名空间的重要说明:【主要看实例四和五】 子类加载所加载的类能够访问到父类加载器所加载的类; 父类加载器所加载的类无法访问到子加载器所加载的类。 实例一: public class MyCat { public MyCat(){ System.out.println("MyCat is loaded by:"+this...

qq_40574305的博客 183

线程上下文类加载器实战分析与难点剖析

在上一次【https://www.cnblogs.com/webor2006/p/9260949.html】已经对ServiceLoader这个类的javadoc通读了一遍,这次来分析一下它是如何来加载驱动的底层细节,先来回顾一下上一次编写的程序: 然后重点是看第一句加载的代码: 那跟进去看一下呗,在看细节之前先来读一下它的javadoc: 而看一下它的实现: 首先获取的是当前线程上下文...

webor2006的博客 106

4.jvm类加载器命名空间实战剖析与透彻理解

类加载器命名空间实战剖析与透彻理解 命名空间 每个类加载器都有自己的命名空间,命名空间是由该加载器及所有的父加载器加载的类组成 在同一个命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类 在不同的命名空间中,有可能出现类的完整名字(包括类的包名)相同的两个类 关于命名空间的重要说明 1、子加载器所加载的类能够访问到父加载器所加载的类 2、父加载器所加载的类无法访问到子类加载器所加载的...

闪电侠-公子的博客 393

八、类加载器深入解析及重要特性剖析

1、类加载过程 其中连接又分为三个阶段:验证、准备、解析。 加载:就是把二进制形式的java类型读入到java虚拟机中 验证: 准备:为类的静态变量分配内存,设置默认值。但是在初始化之前,类变量都没有初始化为真正的初始值。 解析:解析过程就是在类型的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用替换成直接引用 初始化:为类变量赋予正确的初始值。 类实例化:为新的对象分配内存,为实例...

lifeline张的博客 265

JVM中类加载器的分类理解与剖析

VM支持两种类型的加载器,分别是引导类加载器(BootstrapClassLoader)和自定义类加载器(User-Defined ClassLoader)。但是,从概念上来说,自定义类加载器一般指的是程序中开发人员自定义的一类类加载器,但是JAVA虚拟机规范中确没有像我们这样定义,而是将所有派生于抽象类ClassLoader的类加载器都规划为自定义类加载器。

写写平时的技术与感想 2111

17-类加载器双亲委托机制实例深度剖析

类加载器双亲委托机制实例深度剖析 java.lang.ClassLoader protected Class<?> loadClass(String name , boolean resolve) throws ClassNotFoundException ​ Loads the class with the speci...

qq_40574305的博客 196

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

当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把主类加载到JVM。

Myname_China的博客 870

类加载器深入解释及重要特性剖析

一、类加载流程图 二、从加载到类实例化的完整过程 三、类的加载 类的加载的最终产品是位于内存中的Class对象(不涉及到对象)。 Class对象封装了类在方法去内的数据结构,并且向java程序员提供了访问方法区内的数据结构的接口。 两种类型的加载器 Java虚拟机自带的加载器 根类加载器(启动类加载器):Bootstrap...

清风不灭的博客 290
上一篇: 实战:OutOfMemoryError
下一篇: 算法基础一之排序算法
给自己加加油
博客等级 码龄8年 302粉丝 110原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值