高度なJavaプログラミング(11)ClassLoaderクラスローダー

1、ClassLoaderクラスローダー紹介

  Java環境変数でのシステム提供:JVMプロセスの起動時にクラスパスを、このプロパティの役割は主に、つまり、あなたはその後、内部JVMでのパスのクラスローダを指定したクラスにロードすることができ、クラスローダのパスを定義していますクラスローダは、クラスのソースを見つけるための手段を見つけることです。

システムクラスローダ

  あなたは今、クラスローダを取得するためには、それはクラスローダを介して取得しなければならず、オブジェクトClassLoaderクラスを得るために、あなたがのルートを使用しなければならないと言うなら、クラスのクラスの実装方法[反映]:取得した公開クラスローダのgetClassLoader()が、クラスローダ後、その親クラスのClassLoaderクラスオブジェクトを取得し続けることができる:パブリック最終的なクラスローダのgetParentを();

・例:クラスローダを観察

1  クラスメッセージ{
 2  }
 3。 パブリック クラスJavaAPIDemo {
 4。     公共 静的 ボイドメイン(文字列[]引数){
 5。          メッセージclazzクラス= <?>。クラス図6          のSystem.out.println(clazz.getClassLoader()); // 現在のクラスローダを取得します
7。          のSystem.out.println(clazz.getClassLoader()のgetParent()); // 親クラスローダを取得します
。8          のSystem.out.println(clazz.getClassLoader()のgetParent()のgetParent(.. )); // 取得祖父母クラスローダ
9      }
 10  }
 11  / * 
12 jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
 13  jdk.internal.loader.ClassLoaders$PlatformClassLoader@1e643faf
 14  ヌル
 15   * /

  [] [PlatformClassLoader]クラスローダと、以前のバージョンとJDK1.8ローダに設けられたそれ以降のバージョンとJDK1.10 JDK1.9 JDK1.8からJDKにインストールされ、[] ExtClassLoader内部に設けられていますディレクトリが別のextディレクトリを提供し、開発者は、[] * .jarファイルをこのディレクトリにコピーされていることができますので、直接実行することができますが、このような治療の開発は、それは眉をひそめた最初の時間は安全ではありませんそうJDK1.9からは完全に廃止し、そして順に、システムローダとアプリケーションクラスローダとの間で設計のバランスを維持するために、プラットフォームのクラスローダを提供します。

  あなたが得るときにクラスローダは、リフレクションベースの処理負荷のクラスローダを使用して実装することができます。

2、カスタム処理クラスローダ

  セルフオーダーシステムのすべてのクラスローダの最後にロードしたカスタムクラスローダ:明らかにクラスローダ機能の後は、カスタムクラスローダを実装するが、一つのことを覚えておく必要があり、その必要性に応じてすることができます。クラスのためのシステムクラスローダは、CLASSPATHは、パスを見つけるにロードされ、そして、彼らは自己定義されたクラスローダを持っている場合は、開発者のローディング位置で任意のクラスに割り当てることができます。 

①フリープログラムのクラスを記述するために、このクラスは、ディスク上に保存されます。

 1 import java.io.*;
 2 
 3 public class MufasaClassLoader extends ClassLoader {
 4     private static final String MESSAGE_CLASS_PATH="D:"+ File.separator+"Message.class";
 5     /**
 6      * 进行指定类的加载
 7      * @param className 类的完整名称【包.类】
 8      * @return 返回一个指定类的class对象
 9      * @throws Exception 如果类文件不存在则无法加载
10      */
11     public Class<?> loadData(String className)throws Exception{
12         byte[] data=this.loadClassData();//读取二进制数据文件
13         if(data!=null){//读取到数据
14             return super.defineClass(className,data,0,data.length);
15         }
16         return null;
17 
18     }
19     private byte[] loadClassData()throws Exception{//通过文件进行类的加载
20         InputStream input=null;
21         ByteArrayOutputStream bos=null;//将数据加载到内存之中
22         byte[] data=null;
23         try{
24             bos=new ByteArrayOutputStream();//实例化内存流
25             input=new FileInputStream(new File(MESSAGE_CLASS_PATH));//文件流加载
26 //            byte[] data=new byte[1024];//进行读取方式①
27             input.transferTo(bos);//读取数据方式②
28             data= bos.toByteArray();//将所有读取到的字节数组取出
29         }catch (Exception e){
30 
31         }finally {
32             if(input!=null){
33                 input.close();
34             }
35             if(bos!=null){
36                 bos.close();
37             }
38         }
39         return data;
40     }
41 }

④编写测试类实现类加载控制;

 1 package cn.mufasa.demo;
 2 import cn.mufasa.util.MufasaClassLoader;
 3 import java.lang.reflect.Method;
 4 
 5 public class JavaAPIDemo1 {
 6     public static void main(String[] args) throws Exception {
 7         MufasaClassLoader classLoader=new MufasaClassLoader();
 8         Class<?> cls=classLoader.loadData("cn.mufasa.util.Message");//进行类的加载
 9         System.out.println(cls);
10         Object obj=cls.getDeclaredConstructor().newInstance();
11         Method method=cls.getDeclaredMethod("send");
12         method.invoke(obj);
13     }
14 }
15 /*
16 读取到数据
17 class cn.mufasa.util.Message
18 www.cnblogs.com
19  */

  如果在以后结合网络开发的话,就可以通过一个远程的服务器来确定类的功能。

 

⑤观察当前的Message类的加载器的情况

package cn.mufasa.demo;
import cn.mufasa.util.MufasaClassLoader;
import java.lang.reflect.Method;

public class JavaAPIDemo1 {
    public static void main(String[] args) throws Exception {
        MufasaClassLoader classLoader=new MufasaClassLoader();
        Class<?> cls=classLoader.loadData("cn.mufasa.util.Message");//进行类的加载
//        System.out.println(cls);
        System.out.println(cls.getClassLoader());//获取当前类的加载器
        System.out.println(cls.getClassLoader().getParent());//获取父类加载器
        System.out.println(cls.getClassLoader().getParent().getParent());//获取祖父类加载器


    }
}
/*
cn.mufasa.util.MufasaClassLoader@668bc3d5
jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
jdk.internal.loader.ClassLoaders$PlatformClassLoader@3fb6a447
 */

  如果说你先在定义了一个类,这个类的名称定义为:java.lang.String,并且利用了自定义类加载器进行加载处理,这个类将不会被加载,原因:Java之中针对于类加载器提供有双亲加载机制,如果现在要加载的类是由系统提供的类则会由系统类进行加载,如果现在开发者定义的类与系统类定义的名称相同,那么【为了保证系统的安全性】绝对不会加载。

おすすめ

転載: www.cnblogs.com/Mufasa/p/11184713.html