고급 자바 프로그래밍 (11) 클래스 로더 클래스 로더

1, 클래스 로더 클래스 로더 소개

  자바 환경 변수의 시스템 제공 : JVM 프로세스가 시작되면 클래스 경로를이 속성의 역할은 주로 즉, 당신은 다음 내부의 JVM의 경로 클래스 로더를 지정하는 클래스에로드 할 수 있습니다, 클래스 로더 경로를 정의 클래스 로더는 클래스의 소스를 찾을 수있는 방법을 찾을 수있다.

시스템 클래스 로더

  획득 할 때 공공의 ClassLoader getClassLoader를 () : 지금 클래스 로더를 얻기 위해, 다음은 클래스 로더를 통해 얻을 수 있으며, 객체 클래스 로더 클래스를 얻기 위해해야한다고 말한다면, 당신은 [반사] 클래스 클래스 구현 방법의 루트를 사용해야합니다 () 공공 최종 클래스 로더의 getParent를; 클래스 로더는 부모 클래스의 ClassLoader 클래스의 객체를 얻기 위해 계속 후

· 예 : 클래스 로더를 관찰

. 1  메시지 {
 2  }
 3.  공용  클래스 JavaAPIDemo {
 4.      공용  정적  무효 메인 (문자열 []에 args) {
 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   * /

  이후 버전으로부터 JDK1.10 JDK1.9 JDK1.8 [] [PlatformClassLoader] 클래스 로더를 구비하고 이전 버전과 JDK 설치로 JDK1.8 로더는 ExtClassLoader [] 내부에 구비 , 디렉토리, 개발자는 [] * .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