添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
豁达的课本  ·  Method ...·  16 小时前    · 
刀枪不入的马铃薯  ·  The CommonFolders module·  16 小时前    · 
老实的充值卡  ·  DeleteWebCCRuleV2 - ...·  12 小时前    · 
阳刚的青蛙  ·  Geometry—ArcMap | 文档·  12 小时前    · 
留胡子的红薯  ·  Problem with ...·  6 小时前    · 
英姿勃勃的胡萝卜  ·  Store | Windows 版 ...·  2 月前    · 
求醉的胡萝卜  ·  Access Denied·  5 月前    · 
胆小的创口贴  ·  Scenic Route, West LA ...·  6 月前    · 
听话的显示器  ·  Re: kdenlive, ...·  6 月前    · 

(归档:https://www.iteye.com/topic/1126847)

在Java的世界中,ClassLoader用来将Java类装载进JVM使之可以运行。当我们使用java命令使用一些 .class 的java class时,系统会使用默认的ClassLoader将class读入。

在本文中,将详细探讨 ClassLoader 的使用。

动态加载类的几种方法

可以使用下面的几种方法将Class读入:

方法 1 使用 .class

下面的代码会让 String[] 这个class被JVM读入:

Class c = String[].class;  

此时这个class就已经被加载并得到了对应的Class

方法 2: 使用实例的getClass()方法

如果是实例(instance),那么调用它的getClass()方法就可以得到对应的Class。下面是代码示例:

c = new String[1].getClass();  

最后还有通过ClassforName()方法来加载class。

方法 3: 使用 Class.forName()

c = Class.forName("[Ljava.lang.String;");  

上面使用了Class.forName()方法来直接加载字串里面表示的方法。

其中第三个方法中的类名有点奇怪,为什么java.lang.String前面有个L?这个其实是Java的bytecode的命名约定。

在Java中,我们可以用Class.forName()来获取类,比如下面这个例子:

System.out.println(Class.forName("Demo1"));  

运行结果如下:

class Demo1  

但是我们用这种方法获取数组时却会出错:

System.out.println(Class.forName("java.lang.String[]"));  

运行结果如下:

Exception in thread "main" java.lang.ClassNotFoundException: java/lang/String[]  
     at java.lang.Class.forName0(Native Method)  
     at java.lang.Class.forName(Class.java:169)  

这是为什么呢?因为Array的名字与我们看到的并不一致,可以用下述代码测试:

System.out.println(String[].class.getName());  

得到的结果如下:

[Ljava.lang.String;

可以看到,JVM对Array的实际类名编码为:

  • 左括号 + 类别代码 + 类名
  • 因此我们用上面的规则来获取Array class

    Class cls = Class.forName("[Ljava.lang.String;");
    

    因此我们可以得到native type的Array的编码:

    System.out.println("byte[]: " + byte[].class.getName());  
    System.out.println("char[]: " + char[].class.getName());  
    System.out.println("int[]: " + int[].class.getName());  
    System.out.println("long[]: " + long[].class.getName());  
    System.out.println("double[]: " + double[].class.getName());  
    System.out.println("float[]: " + float[].class.getName());  
    

    结果如下:

    byte[]: [B  
    char[]: [C  
    int[]: [I  
    long[]: [J  
    double[]: [D  
    float[]: [F
    

    可以看到每一种native类型数组对应的JVM中的类名,我们需要知道Java语言的这个约定习惯。

    什么是ClassLoader

    ClassLoader是Java中的类加载器,可以帮助你把一个Class动态地加载进JVM。每一个JVM环境中,都有一个默认的ClassLoader,我们可以用下述方法获得默认的ClassLoader:

    ClassLoader.getSystemClassLoader()
    

    我们撰写一个ClassLoaderName如下所示:

    public class ClassLoaderName {
        public static void main(String[] args) throws Exception {
            System.out.println(ClassLoader.getSystemClassLoader().toString());
    

    上面的代码运行结果如下:

    jdk.internal.loader.ClassLoaders$AppClassLoader@512ddf17
    

    从上面的结果可以看到实际的class loader。

    ClassLoader的使用方法

    下面给出一个完整的使用class loader加载class的例子,代码如下:

    package io.alchemystudio.classloader;
    public class MyClass {
        public static void main(String[] args) throws Exception {
            Class clazz = ClassLoader
                    .getSystemClassLoader()
                    .loadClass("io.alchemystudio.classloader.MyClass");
            MyClass myClass = (MyClass) clazz.getDeclaredConstructor().newInstance();
            myClass.sayHello();
        private void sayHello() {
            System.out.println("Hello, world!");
    

    如上所示,我们首先使用ClassLoader.getSystemClassLoader().loadClass()方法来加载MyClass;然后通过clazz.getDeclaredConstructor().newInstance()生成class的实例,最后使用这个实例的sayHello()方法。执行上面的代码结果如下:

    Hello, world!
    

    以上就是class loader的一个基础的使用方法。在本系列文章的后续文章中,我们将动手制作一个ClassLoader,并学习ClassLoader的命名空间Namespace。

    本系列文章中使用的源代码

    接下来的讲解过程中,要大量用到代码示例,我将这些代码统一放到了github上面:

  • GitHub - liweinan/java-snippets: Collections of code pieces
  • 这是一个基于maven的项目,因此可以很方便地打包执行,接下来的讲解将大量用到这个项目中的代码。

    这篇文章的样例代码放在了这里:

  • java-snippets/ClassLoaderName.java at master · alchemy-studio/java-snippets · GitHub
  • java-snippets/MyClass.java at master · alchemy-studio/java-snippets · GitHub
  • 有兴趣可以运行看看。

    阿男的小窝 / Published on Apr 11, 2020

    Powered by Jekyll and Theme by solid

    If you have any question want to ask or find bugs regarding