JVM入门实践

目录

类加载执行过程

类加载器和双亲委派机制

何为双亲委派?

双亲委派的作用 

自定义类加载器

打破双亲委派


类加载执行过程

我们看如下代码,当我们启动的时候,main方法将会被运行,这个执行过程其实是由我们的类加载器来完成的。

package com.jvm;

public class JvmRunner {
   public static final int month  = 5;

   public void show(){
       int one = 10;
       int two = 11;
       int result = one+two ;
       System.out.println("result = " + result);
   }
    public static void main(String[] args) {
        JvmRunner jvmRunner  = new JvmRunner();
        jvmRunner.show();
    }
}

我们来看看等同于如下执行语句,具体来干了什么

// 切换到对应/target/classes目录中,运行.class文件
java com.jvm.JvmRunner

其中loadClass的类加载过程有如下几个步骤:

加载->验证->准备->解析->初始化->使用->卸载

  • 加载:硬盘上寻找并读取对应类的class文件
  • 验证:校验字节码文件得正确性
  • 准备:给类的静态变量分配内存,并赋予默认值。例如:
    public static final int month  = 5; 这里会将基础类型的int类型赋值为0。
  • 解析:将符号引用替换为直接引用。符号引用顾名思义,比如一个main方法名可以理解成一个符号,在这里将会被具体映射到内存中某个具体地址,这个就是所谓的静态链接;与之对应的就是动态链接,运行过程中将符号替换为直接引用。例如:main方法中,我们调用的show()方法;
  • 初始化:对类的静态变量初始化指定的值,同时会执行静态代码快方法(注:静态代码块执行顺序优先于构造方法)

通过将class文件反编译,我们来认识一下符号引用,其中 【"Constant pool"】从#1~#60都是符号引用代表的名称。

控制台执行脚本:javap -c -v com.jvm.JvmRunner

Classfile /target/classes/com/jvm/JvmRunner.class
  Last modified 2022-5-17; size 1020 bytes
  MD5 checksum f723d16e6807d1f8c4eb64adc08753e1
  Compiled from "JvmRunner.java"
public class com.jvm.JvmRunner
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #13.#37        // java/lang/Object."<init>":()V
   #2 = Fieldref           #38.#39        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Class              #40            // java/lang/StringBuilder
   #4 = Methodref          #3.#37         // java/lang/StringBuilder."<init>":()V
   #5 = String             #41            // result =
   #6 = Methodref          #3.#42         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #7 = Methodref          #3.#43         // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   #8 = Methodref          #3.#44         // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #9 = Methodref          #45.#46        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #10 = Class              #47            // com/jvm/JvmRunner
  #11 = Methodref          #10.#37        // com/jvm/JvmRunner."<init>":()V
  #12 = Methodref          #10.#48        // com/jvm/JvmRunner.show:()V
  #13 = Class              #49            // java/lang/Object
  #14 = Utf8               month
  #15 = Utf8               I
  #16 = Utf8               ConstantValue
  #17 = Integer            5
  #18 = Utf8               <init>
  #19 = Utf8               ()V
  #20 = Utf8               Code
  #21 = Utf8               LineNumberTable
  #22 = Utf8               LocalVariableTable
  #23 = Utf8               this
  #24 = Utf8               Lcom/jvm/JvmRunner;
  #25 = Utf8               show
  #26 = Utf8               one
  #27 = Utf8               two
  #28 = Utf8               result
  #29 = Utf8               main
  #30 = Utf8               ([Ljava/lang/String;)V
  #31 = Utf8               args
  #32 = Utf8               [Ljava/lang/String;
  #33 = Utf8               jvmRunner
  #34 = Utf8               MethodParameters
  #35 = Utf8               SourceFile
  #36 = Utf8               JvmRunner.java
  #37 = NameAndType        #18:#19        // "<init>":()V
  #38 = Class              #50            // java/lang/System
  #39 = NameAndType        #51:#52        // out:Ljava/io/PrintStream;
  #40 = Utf8               java/lang/StringBuilder
  #41 = Utf8               result =
  #42 = NameAndType        #53:#54        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #43 = NameAndType        #53:#55        // append:(I)Ljava/lang/StringBuilder;
  #44 = NameAndType        #56:#57        // toString:()Ljava/lang/String;
  #45 = Class              #58            // java/io/PrintStream
  #46 = NameAndType        #59:#60        // println:(Ljava/lang/String;)V
  #47 = Utf8               com/jvm/JvmRunner
  #48 = NameAndType        #25:#19        // show:()V
  #49 = Utf8               java/lang/Object
  #50 = Utf8               java/lang/System
  #51 = Utf8               out
  #52 = Utf8               Ljava/io/PrintStream;
  #53 = Utf8               append
  #54 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #55 = Utf8               (I)Ljava/lang/StringBuilder;
  #56 = Utf8               toString
  #57 = Utf8               ()Ljava/lang/String;
  #58 = Utf8               java/io/PrintStream
  #59 = Utf8               println
  #60 = Utf8               (Ljava/lang/String;)V
{
  public static final int month;
    descriptor: I
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    ConstantValue: int 5

  public com.jvm.JvmRunner();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/jvm/JvmRunner;

  public void show();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=4, args_size=1
         0: bipush        10
         2: istore_1
         3: bipush        11
         5: istore_2
         6: iload_1
         7: iload_2
         8: iadd
         9: istore_3
        10: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        13: new           #3                  // class java/lang/StringBuilder
        16: dup
        17: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        20: ldc           #5                  // String result =
        22: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        25: iload_3
        26: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        29: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        32: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        35: return
      LineNumberTable:
        line 7: 0
        line 8: 3
        line 9: 6
        line 10: 10
        line 11: 35
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      36     0  this   Lcom/jvm/JvmRunner;
            3      33     1   one   I
            6      30     2   two   I
           10      26     3 result   I

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #10                 // class com/jvm/JvmRunner
         3: dup
         4: invokespecial #11                 // Method "<init>":()V
         7: astore_1
         8: aload_1
         9: invokevirtual #12                 // Method show:()V
        12: return
      LineNumberTable:
        line 13: 0
        line 14: 8
        line 15: 12
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0  args   [Ljava/lang/String;
            8       5     1 jvmRunner   Lcom/jvm/JvmRunner;
    MethodParameters:
      Name                           Flags
      args
}
SourceFile: "JvmRunner.java"

类加载器和双亲委派机制

  • 引导类加载器:负责加载支撑jvm运行的位于jre的lib目录下得核心类库,比如rt.jar、charsets.jar等。
  • 扩展类加载器:ext目录下得jar包。
  • 应用程序类加载器:负责加载classpath路径下的类包,也就是我们写得代码类。
  • 自定义加载器:负责加载用户自定义路径下得类包。

我们先通过一个代码示例来了解一下各个类加载器

package com.jvm;


import com.sun.crypto.provider.DESKeyFactory;
import sun.misc.Launcher;

import java.net.URL;

/**
 * 我们所看到的应用程序类加载器包含引导类加载器的jar包,是因为懒加载问题哟
 * jar包中的方法,是用到的时候才会加载
 */
public class ClassLoaderUnit {

    public static void main(String[] args) {
        System.out.println("String类属于rt.jar为引导类加载器,c++实现无法查看,返回结果=null;result="+String.class.getClassLoader());
        System.out.println("扩展类加载器,返回结果:sun.misc.Launcher$ExtClassLoader@17d10166;result="+DESKeyFactory.class.getClassLoader());
        System.out.println("用户自己类加载器,返回结果:sun.misc.Launcher$AppClassLoader@18b4aac2;result="+ClassLoaderUnit.class.getClassLoader());
        System.out.println("-----------\n");

        ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
        ClassLoader extClassLoader = appClassLoader.getParent();
        ClassLoader bootstrapLoader = extClassLoader.getParent();
        System.out.println("bootstrapLoader为c++实现,所以返回结果为null;result="+bootstrapLoader);
        System.out.println("appClassLoader的父类加载器为extClassLoader;result="+extClassLoader);
        System.out.println("SystemClassLoader默认就是appClassLoader,就是我们说的默认类加载器;result="+appClassLoader);
        System.out.println("-----------\n");
        System.out.println("打印bootstrapLoader加载的文件");
        URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
        for (int i = 0; i < urLs.length; i++) {
            System.out.println(urLs[i]);
        }
        System.out.println("-----------\n");
        System.out.println("打印extstrapLoader加载的文件");
        System.out.println(System.getProperty("java.ext.dirs"));


        System.out.println("-----------\n");
        System.out.println("打印appstrapLoader加载的文件");
        System.out.println(System.getProperty("java.class.path"));

    }
    /*
    结果一览:
    String类属于rt.jar为引导类加载器,c++实现无法查看,返回结果=null;result=null
扩展类加载器,返回结果:sun.misc.Launcher$ExtClassLoader@17d10166;result=sun.misc.Launcher$ExtClassLoader@17d10166
用户自己类加载器,返回结果:sun.misc.Launcher$AppClassLoader@18b4aac2;result=sun.misc.Launcher$AppClassLoader@18b4aac2
-----------

bootstrapLoader为c++实现,所以返回结果为null;result=null
appClassLoader的父类加载器为extClassLoader;result=sun.misc.Launcher$ExtClassLoader@17d10166
SystemClassLoader默认就是appClassLoader,就是我们说的默认类加载器;result=sun.misc.Launcher$AppClassLoader@18b4aac2
-----------

打印bootstrapLoader加载的文件
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/resources.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/rt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/sunrsasign.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/jsse.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/jce.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/charsets.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/jfr.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/classes
-----------

打印extstrapLoader加载的文件
/Users/dolphin/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
-----------

打印appstrapLoader加载的文件
/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/lib/tools.jar:/Users/dolphin/goodfuture/selfproject/SpringBootTest/target/classes:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot-starter/2.3.2.RELEASE/spring-boot-starter-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot/2.3.2.RELEASE/spring-boot-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/spring-context/5.2.8.RELEASE/spring-context-5.2.8.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot-autoconfigure/2.3.2.RELEASE/spring-boot-autoconfigure-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot-starter-logging/2.3.2.RELEASE/spring-boot-starter-logging-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/apache/logging/log4j/log4j-to-slf4j/2.13.3/log4j-to-slf4j-2.13.3.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/apache/logging/log4j/log4j-api/2.13.3/log4j-api-2.13.3.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/slf4j/jul-to-slf4j/1.7.30/jul-to-slf4j-1.7.30.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/jakarta/annotation/jakarta.annotation-api/1.3.5/jakarta.annotation-api-1.3.5.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/spring-core/5.2.8.RELEASE/spring-core-5.2.8.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/spring-jcl/5.2.8.RELEASE/spring-jcl-5.2.8.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/yaml/snakeyaml/1.26/snakeyaml-1.26.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/cloud/spring-cloud-starter-alibaba-nacos-discovery/2.2.5.RELEASE/spring-cloud-starter-alibaba-nacos-discovery-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/cloud/spring-cloud-alibaba-commons/2.2.5.RELEASE/spring-cloud-alibaba-commons-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/nacos/nacos-client/1.4.1/nacos-client-1.4.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/nacos/nacos-common/1.4.1/nacos-common-1.4.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/commons-io/commons-io/2.2/commons-io-2.2.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/apache/httpcomponents/httpasyncclient/4.1.4/httpasyncclient-4.1.4.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/apache/httpcomponents/httpcore/4.4.13/httpcore-4.4.13.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/apache/httpcomponents/httpcore-nio/4.4.13/httpcore-nio-4.4.13.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/nacos/nacos-api/1.4.1/nacos-api-1.4.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/google/guava/guava/29.0-jre/guava-29.0-jre.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/commons-codec/commons-codec/1.14/commons-codec-1.14.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/fasterxml/jackson/core/jackson-core/2.11.1/jackson-core-2.11.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/fasterxml/jackson/core/jackson-databind/2.11.1/jackson-databind-2.11.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/fasterxml/jackson/core/jackson-annotations/2.11.1/jackson-annotations-2.11.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/prometheus/simpleclient/0.5.0/simpleclient-0.5.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/spring/spring-context-support/1.0.10/spring-context-support-1.0.10.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/cloud/spring-cloud-commons/2.2.5.RELEASE/spring-cloud-commons-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/security/spring-security-crypto/5.3.3.RELEASE/spring-security-crypto-5.3.3.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/cloud/spring-cloud-context/2.2.5.RELEASE/spring-cloud-context-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/cloud/spring-cloud-starter-netflix-ribbon/2.2.5.RELEASE/spring-cloud-starter-netflix-ribbon-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/cloud/spring-cloud-netflix-ribbon/2.2.5.RELEASE/spring-cloud-netflix-ribbon-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/cloud/spring-cloud-netflix-archaius/2.2.5.RELEASE/spring-cloud-netflix-archaius-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/cloud/spring-cloud-starter-netflix-archaius/2.2.5.RELEASE/spring-cloud-starter-netflix-archaius-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/commons-configuration/commons-configuration/1.8/commons-configuration-1.8.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/netflix/ribbon/ribbon/2.3.0/ribbon-2.3.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/netflix/ribbon/ribbon-transport/2.3.0/ribbon-transport-2.3.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/reactivex/rxnetty-contexts/0.4.9/rxnetty-contexts-0.4.9.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/reactivex/rxnetty-servo/0.4.9/rxnetty-servo-0.4.9.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/javax/inject/javax.inject/1/javax.inject-1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/reactivex/rxnetty/0.4.9/rxnetty-0.4.9.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/netflix/ribbon/ribbon-core/2.3.0/ribbon-core-2.3.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/commons-lang/commons-lang/2.6/commons-lang-2.6.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/netflix/ribbon/ribbon-httpclient/2.3.0/ribbon-httpclient-2.3.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/apache/httpcomponents/httpclient/4.5.12/httpclient-4.5.12.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/sun/jersey/jersey-client/1.19.1/jersey-client-1.19.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/sun/jersey/jersey-core/1.19.1/jersey-core-1.19.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/javax/ws/rs/jsr311-api/1.1.1/jsr311-api-1.1.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/sun/jersey/contribs/jersey-apache-client4/1.19.1/jersey-apache-client4-1.19.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/netflix/servo/servo-core/0.12.21/servo-core-0.12.21.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/netflix/netflix-commons/netflix-commons-util/0.3.0/netflix-commons-util-0.3.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/netflix/ribbon/ribbon-loadbalancer/2.3.0/ribbon-loadbalancer-2.3.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/netflix/netflix-commons/netflix-statistics/0.1.1/netflix-statistics-0.1.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/reactivex/rxjava/1.3.8/rxjava-1.3.8.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/cloud/spring-cloud-starter-openfeign/2.2.5.RELEASE/spring-cloud-starter-openfeign-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/cloud/spring-cloud-starter/2.2.5.RELEASE/spring-cloud-starter-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/security/spring-security-rsa/1.0.9.RELEASE/spring-security-rsa-1.0.9.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/bouncycastle/bcpkix-jdk15on/1.64/bcpkix-jdk15on-1.64.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/bouncycastle/bcprov-jdk15on/1.64/bcprov-jdk15on-1.64.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/cloud/spring-cloud-openfeign-core/2.2.5.RELEASE/spring-cloud-openfeign-core-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot-starter-aop/2.3.2.RELEASE/spring-boot-starter-aop-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/github/openfeign/form/feign-form-spring/3.8.0/feign-form-spring-3.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/github/openfeign/form/feign-form/3.8.0/feign-form-3.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/spring-web/5.2.8.RELEASE/spring-web-5.2.8.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/spring-beans/5.2.8.RELEASE/spring-beans-5.2.8.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/github/openfeign/feign-core/10.10.1/feign-core-10.10.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/github/openfeign/feign-slf4j/10.10.1/feign-slf4j-10.10.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/github/openfeign/feign-hystrix/10.10.1/feign-hystrix-10.10.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/netflix/archaius/archaius-core/0.7.6/archaius-core-0.7.6.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/netflix/hystrix/hystrix-core/1.5.18/hystrix-core-1.5.18.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/cloud/spring-cloud-starter-alibaba-nacos-config/2.2.5.RELEASE/spring-cloud-starter-alibaba-nacos-config-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/cloud/spring-cloud-starter-alibaba-sentinel/2.2.5.RELEASE/spring-cloud-starter-alibaba-sentinel-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-transport-simple-http/1.8.0/sentinel-transport-simple-http-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-transport-common/1.8.0/sentinel-transport-common-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-datasource-extension/1.8.0/sentinel-datasource-extension-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/fastjson/1.2.71/fastjson-1.2.71.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-annotation-aspectj/1.8.0/sentinel-annotation-aspectj-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-core/1.8.0/sentinel-core-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/aspectj/aspectjrt/1.9.6/aspectjrt-1.9.6.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/aspectj/aspectjweaver/1.9.6/aspectjweaver-1.9.6.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/cloud/spring-cloud-circuitbreaker-sentinel/2.2.5.RELEASE/spring-cloud-circuitbreaker-sentinel-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-reactor-adapter/1.8.0/sentinel-reactor-adapter-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-spring-webflux-adapter/1.8.0/sentinel-spring-webflux-adapter-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-spring-webmvc-adapter/1.8.0/sentinel-spring-webmvc-adapter-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-parameter-flow-control/1.8.0/sentinel-parameter-flow-control-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/googlecode/concurrentlinkedhashmap/concurrentlinkedhashmap-lru/1.4.2/concurrentlinkedhashmap-lru-1.4.2.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-cluster-server-default/1.8.0/sentinel-cluster-server-default-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-cluster-common-default/1.8.0/sentinel-cluster-common-default-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/netty/netty-handler/4.1.51.Final/netty-handler-4.1.51.Final.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/netty/netty-common/4.1.51.Final/netty-common-4.1.51.Final.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/netty/netty-resolver/4.1.51.Final/netty-resolver-4.1.51.Final.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/netty/netty-buffer/4.1.51.Final/netty-buffer-4.1.51.Final.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/netty/netty-transport/4.1.51.Final/netty-transport-4.1.51.Final.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/netty/netty-codec/4.1.51.Final/netty-codec-4.1.51.Final.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/csp/sentinel-cluster-client-default/1.8.0/sentinel-cluster-client-default-1.8.0.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/alibaba/cloud/spring-cloud-alibaba-sentinel-datasource/2.2.5.RELEASE/spring-cloud-alibaba-sentinel-datasource-2.2.5.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot-starter-actuator/2.3.2.RELEASE/spring-boot-starter-actuator-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot-actuator-autoconfigure/2.3.2.RELEASE/spring-boot-actuator-autoconfigure-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot-actuator/2.3.2.RELEASE/spring-boot-actuator-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.11.1/jackson-datatype-jsr310-2.11.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/io/micrometer/micrometer-core/1.5.3/micrometer-core-1.5.3.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/hdrhistogram/HdrHistogram/2.1.12/HdrHistogram-2.1.12.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/latencyutils/LatencyUtils/2.0.3/LatencyUtils-2.0.3.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot-starter-web/2.3.2.RELEASE/spring-boot-starter-web-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot-starter-json/2.3.2.RELEASE/spring-boot-starter-json-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.11.1/jackson-datatype-jdk8-2.11.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.11.1/jackson-module-parameter-names-2.11.1.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/boot/spring-boot-starter-tomcat/2.3.2.RELEASE/spring-boot-starter-tomcat-2.3.2.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.37/tomcat-embed-core-9.0.37.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/glassfish/jakarta.el/3.0.3/jakarta.el-3.0.3.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.37/tomcat-embed-websocket-9.0.37.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/spring-webmvc/5.2.8.RELEASE/spring-webmvc-5.2.8.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/spring-aop/5.2.8.RELEASE/spring-aop-5.2.8.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/springframework/spring-expression/5.2.8.RELEASE/spring-expression-5.2.8.RELEASE.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/projectlombok/lombok/1.18.20/lombok-1.18.20.jar:/Users/dolphin/goodfuture/soft/apache-maven-3.8.1/repository/org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.jar:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar

    
    
    
     */
}

何为双亲委派?

以下图来解释说明:当加载一个类的时候,先由应用程序类加载器向扩展类加载器发出请求,看看扩展类加载器中有没有要加载的类,如果有则返回,没有则继续向引导类加载器发出请求,看看引导类加载器中有没有要加载的类,如果有则返回,没有则将查找的任务交给请求方,一直到应用类加载器,如果依旧不存在,则报错。

双亲委派的作用 

  • 沙箱安全:如果自己写了一个和引导类一模一样的类,那么只会加载系统的,保证系统安全性
  • 避免重复加载

其实在这里我们也可以猜测一下,为什么要从应用程序类加载器作为开始,而不是由引导类加载程序开始?

我觉得1.大牛就是这样设计的;2.我觉得90%都是运行自己的代码,所以除了第一次做一次查询外,其它时间都是直接在应用程序类加载器中实现了,毕竟一个系统,大部分都是我们自己写的代码

自定义类加载器

自定义类加载器重点便是继承java.lang.ClassLoader类。该类有2个核心方法,一个是loadClass(String name,boolean resolve)实现了双亲委派机制,另一个就是findClass方法,用于我们寻找指定目录下的class文件。

步骤:

  1. 创建一个测试类LoaderPrint,用于类加载器查询并加载
  2. 创建一个继承了ClassLoader的测试类SelfLoader(SelfClassLoader),并重写了里面的findClass方法
  3. 在硬盘上随便找一个目录,并按照测试类LoaderPrint所属包路径,创建目录
  4. 编译文件,将LoaderPrint.class文件,丢进步骤3最终目录中
  5. 重命名LoaderPrint.java或者删除,执行查看效果(1.如果没有改变项目中该文件,那么按照双亲委派机制,会用应用程序类加载器来加载target/classes中对应的类文件)

代码如下:

文件1:

package com.jvm;

/**
 * 描述
 *
 * @author 
 * @version 1.0
 * @date 2022/05/17 23:17:23
 */
public class LoaderPrint {

    //public static String msg = "这是硬盘中的文件";
    public static String msg = "这是内存中的文件";


    public void sout(){
        System.out.println(msg);
    }
}

文件2:

package com.jvm;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 描述
 *
 * @author
 * @version 1.0
 * @date 2022/05/17 23:01:02
 */
public class SelfClassLoader {

    static class SelfLoader extends ClassLoader{
        private String classPath;
        public SelfLoader(String classPath){
            this.classPath =  classPath;
        }

        /**
         * 将字节码文件输出到字节数组中
         * @param name
         * @return
         * @throws Exception
         */
        private byte[] loadByte(String name){
            name  = name.replaceAll("\\.","/");
            String url =classPath+"/"+name+".class";
            System.out.println("url = " + url);
            try {
                InputStream is = new FileInputStream(url);
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                byte[] buffer = new byte[2048];
                int num = 0;
                while ((num = is.read(buffer)) != -1) {
                    stream.write(buffer, 0, num);
                }
                return stream.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return null;

        }
        /**
         * 这个类在classLoader里面是空实现,所以我们这里是重点继承,并加以实现
         * 根据字节数组生成class对象
         * @param name
         * @return
         * @throws ClassNotFoundException
         */
        protected Class<?> findClass(String name) throws ClassNotFoundException {

            try{
                byte[]data = loadByte(name);
                System.out.println("name = " + name);
                return defineClass(name,data,0,data.length);
            }catch (Exception e){
                throw new ClassNotFoundException();
            }
        }
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        String loadPath = "/Users/dolphin/logs";
        String classPath = "com.jvm.LoaderPrint";
        SelfLoader selfLoader = new SelfLoader(loadPath);
        Class clazz = selfLoader.loadClass(classPath);
        Object o = clazz.newInstance();
        Method method = clazz.getDeclaredMethod("sout",null);
        method.invoke(o,null);
        System.out.println(clazz.getClassLoader().getClass().getName());
    }

遇见的问题:

将本地硬盘中class文件转换成Class对象,调用了方法

defineClass(String name, byte[] b, int off, int len),这里需要注意这个传入的字节数组,该方法最终会调用验证环节,即是否合法的class文件。本次由于我误操作导致传入的字节数组为空,报错魔法值错误

Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 0 in class file com/jvm/LoaderPrint
     at java.lang.ClassLoader.defineClass1(Native Method)
     at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
     at java.lang.ClassLoader.defineClass(ClassLoader.java:635)
     at com.jvm.SelfClassLoader$SelfLoader.findClass(SelfClassLoader.java:50)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
     at com.jvm.SelfClassLoader.main(SelfClassLoader.java:61)

打破双亲委派

 首先我们自己先创建一个java.lang.String类,并运行,看看效果。报错:

注意:如果你测试的时候,你其它类里面有使用到了String类,那么会提示你对应你用到的String里面的其它方法错误。

注:jdk是不允许你威胁到它核心库的。

错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
   public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application

就像tomcat一样,不同的项目,加载相同的jar包,仅仅是版本不同,怎么做到的,我们来实现一下。其实这个重点就是我们上面提到过的loadClass方法。

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 (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

我们上述源码中ClassLoader中的方法复制过来重写其中方法:

注:注意Object是所有类的父类,所以这个还得由jvm来处理,我们没有权限操作,否则会报如下图2错

 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 {
                        //TODO 注意Object是所有类的父类,所以这个还得由jvm来处理,我们没有权限操作
                        if(!name.startsWith("com.jvm")){
                            c = this.getParent().loadClass(name);
                        }else{
                            c= findClass(name);
                        }
                    } catch (ClassNotFoundException e) {
                        // ClassNotFoundException thrown if class not found
                        // from the non-null parent class loader
                    }

                    if (c == null) {
                        // If still not found, then invoke findClass in order
                        // to find the class.
                        long t1 = System.nanoTime();
                        c = findClass(name);

                        // this is the defining class loader; record the stats
                        sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                        sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                        sun.misc.PerfCounter.getFindClasses().increment();
                    }
                }
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        }
    }

执行报错:

java.io.FileNotFoundException: /Users/dolphin/logs/java/lang/Object.class (No such file or directory)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at java.io.FileInputStream.<init>(FileInputStream.java:93)
	at com.jvm.SelfClassLoader$SelfLoader.loadByte(SelfClassLoader.java:33)
	at com.jvm.SelfClassLoader$SelfLoader.findClass(SelfClassLoader.java:58)
	at com.jvm.SelfClassLoader$SelfLoader.loadClass(SelfClassLoader.java:80)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	at java.lang.ClassLoader.defineClass1(Native Method)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值