java 상해류 캐리어의 양친위 파견 및 양친위 타파

java 상해류 캐리어의 양친위 파견 및 양친위 타파
일반적인 장면에서 자바의 기본 클래스 로더를 사용하면 되지만, 때로는 특정한 목적을 달성하기 위해 자신의 클래스 로더를 실현해야 한다. 예를 들어 클래스 라이브러리의 상호 격리, 예를 들어 열배치 재로더 기능을 달성하기 위해서다.이 때 클래스 캐리어를 정의하고 클래스 캐리어가 각자의 라이브러리 자원을 불러와 자원 격리 효과를 얻도록 해야 한다.자원에 대한 적재에 있어서 양친위파 메커니즘을 그대로 사용할 수도 있고 양친위파 메커니즘을 깨뜨릴 수도 있다.
1. 양친위 파견 메커니즘을 따라 사용자 정의 클래스 캐리어를 사용하는 것은 매우 간단하다. ClassLoader 클래스를 계승하고findClass 방법을 다시 쓰기만 하면 된다.다음 예:
① 먼저 불러올 클래스 Test를 정의합니다. 이것은 간단합니다. 단지 구축 함수에서 어떤 클래스 불러올 클래스를 출력할 뿐입니다.

public class Test {

  public Test(){
    System.out.println(this.getClass().getClassLoader().toString());
  }

}

② TestClassLoader 클래스 상속 ClassLoader를 정의하고 findClass 방법을 다시 작성합니다. 이 방법은 Test를 읽는 것입니다.class 바이트 흐름을 부모 클래스로 전송하는 defineClass 방법입니다.그런 다음 사용자 정의 누적 로더 TestClassLoader를 통해 테스트를 수행할 수 있습니다.class를 로드합니다. 로드가 완료되면 "TestLoader"가 출력됩니다.

public class TestClassLoader extends ClassLoader {

  private String name;

  public TestClassLoader(ClassLoader parent, String name) {
    super(parent);
    this.name = name;
  }

  @Override
  public String toString() {
    return this.name;
  }

  @Override
  public Class<?> findClass(String name) {

    InputStream is = null;
    byte[] data = null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
      is = new FileInputStream(new File("d:/Test.class"));
      int c = 0;
      while (-1 != (c = is.read())) {
        baos.write(c);
      }
      data = baos.toByteArray();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        is.close();
        baos.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return this.defineClass(name, data, 0, data.length);
  }

  public static void main(String[] args) {
    TestClassLoader loader = new TestClassLoader(
        TestClassLoader.class.getClassLoader(), "TestLoader");
    Class clazz;
    try {
      clazz = loader.loadClass("test.classloader.Test");
      Object object = clazz.newInstance();
    } catch (Exception e) {
      e.printStackTrace();
    } 
  }

}

둘째, 양친위 파견 메커니즘을 타파하려면 ClassLoader 클래스를 계승해야 할 뿐만 아니라loadClass와findClass 방법을 다시 써야 한다. 다음과 같다.
① Test 클래스를 정의합니다.

public class Test {
  public Test(){
    System.out.println(this.getClass().getClassLoader().toString());
  }
}
② ClassLoader를 계승하는 TestClassLoader N 클래스를 다시 정의합니다. 이 클래스는 앞의 TestClassLoader 클래스와 매우 비슷하지만findClass 방법을 다시 쓰는 것 외에loadClass 방법을 다시 썼습니다. 기본적인loadClass 방법은 양친위 파견 메커니즘의 논리를 실현하는 것입니다. 즉, 상위 캐리어를 먼저 불러오게 하고 불러올 수 없을 때 스스로 불러옵니다.여기에서 양친위 파견 메커니즘을 파괴하기 위해서는loadClass 방법을 다시 써야 합니다. 즉, 시스템 클래스 마운터에 맡기고 마운트에 실패해야 자신이 마운트할 수 있습니다.그것은 부류 캐리어에 우선적으로 맡기지 않았기 때문에 양친 위임 메커니즘을 깨뜨렸다.

public class TestClassLoaderN extends ClassLoader {

  private String name;

  public TestClassLoaderN(ClassLoader parent, String name) {
    super(parent);
    this.name = name;
  }

  @Override
  public String toString() {
    return this.name;
  }

  @Override
  public Class<?> loadClass(String name) throws ClassNotFoundException {
    Class<?> clazz = null;
    ClassLoader system = getSystemClassLoader();
    try {
      clazz = system.loadClass(name);
    } catch (Exception e) {
      // ignore
    }
    if (clazz != null)
      return clazz;
    clazz = findClass(name);
    return clazz;
  }

  @Override
  public Class<?> findClass(String name) {

    InputStream is = null;
    byte[] data = null;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
      is = new FileInputStream(new File("d:/Test.class"));
      int c = 0;
      while (-1 != (c = is.read())) {
        baos.write(c);
      }
      data = baos.toByteArray();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        is.close();
        baos.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return this.defineClass(name, data, 0, data.length);
  }

  public static void main(String[] args) {
    TestClassLoaderN loader = new TestClassLoaderN(
        TestClassLoaderN.class.getClassLoader(), "TestLoaderN");
    Class clazz;
    try {
      clazz = loader.loadClass("test.classloader.Test");
      Object object = clazz.newInstance();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}

읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!

좋은 웹페이지 즐겨찾기