Whiteship's Note


[ClassLoader 퀴즈 4] SpringSprout가 알고 있는 Whiteship은 누구인가?

Java : 2010.02.21 21:29


퀴즈 3번을 다시 낸거라 생각히셔도 되겠습니다. 2, 3번을 푸셨다면 이 문제도 역시 간단하게 푸실 수 있을 겁니다.

   @Test
    public void classCastException() throws Exception {
        URLClassLoader uCL1 = new FileUrlClassLoader(TEMP_CLASSPATH);
        Class springSproutClass = uCL1.loadClass(TEMP_SPRING_SPROUT);
        Object springSprout = springSproutClass.newInstance();
        Class whiteshipClass1 = uCL1.loadClass(TEMP_WHITESHIP);
        Object whiteship1 = whiteshipClass1.newInstance();

        URLClassLoader uCL2 = new FileUrlClassLoader(TEMP_CLASSPATH);
        Class whiteshipClass2 = uCL2.loadClass(TEMP_WHITESHIP);
        Object whiteship2 = whiteshipClass2.newInstance();

        Method cast = springSproutClass.getMethod("castWhiteship", Object.class);
        cast.invoke(springSprout, whiteship1); // C1
        cast.invoke(springSprout, whiteship2); // C2
    }

TEMP_CLASSPATH는 이 프로젝트의 기본 클래스패스가 아닙니다.
TEMP_SPRING_SPROUT는 SpringSprout.java 클래스의 이름이고
TEMP_WHITESHIP은 Whiteship.java 클래스의 이름을 줍니다.

SpringSprout 클래스에 있는 castWhiteship 메서드는 다음과 같습니다.

    public void castWhiteship(Object object){
        Whiteship2 whiteship = (Whiteship2)object;
    }

C1에서는 아무 일 없지만 C2에서는 바로 저 부분에서 ClassCastException이 발생하죠. 그 이유는 퀴즈 3에 대한 답으로 성윤군이 달아줬지요.

그럼 이번 문제는 조금 다르게...

public void hi(Whiteship whipteship){
    // 띵까 띵까..
}

SpringSprout에 이런 메서드가 있을 때 저 메서드를 호출할 때 whiteship1와 whiteship2 객체를 각각 전달해 준다면 어떤 일이 벌어질까요?

        Method cast = springSproutClass.getMethod("hi", whiteshipClass1);
        cast.invoke(springSprout, whiteship1); // H1
        cast.invoke(springSprout, whiteship2); // H2


top


[ClassLoader 퀴즈 3] Whiteship은 Whiteship일까 아닐까?

Java : 2010.02.19 16:46


퀴즈 2번 문제의 정답을 맞추신 분이라면 클래스패스와 클래스로더의 관계에 대해 잘 알고 계신 것 같습니다. temp 폴더는 클래스패스에 들어있지 않다고 했었죠. 따라서 URLClassLoader.loadClass를 실행했을 때 그것의 상위 클래스로더인 AppClassLoader가 읽어오지 못하고 자기 자신이 가져오게 됩니다. 

따라서 결국 제가 원하던대로 whiteshipClass1과 whtieshipClass2는 각각 다른 클래스로더(uCL1, uCL2)들이 가져오게 됐습니다.

이쯤 말씀드렸으니.. 정답은 뭐... 당연한 거니까 패스.

    @Test(expected = ClassCastException.class)
    public void classCastException() throws Exception {
        URL url = new URL("file:C:/intellij9-workspace/springsprout2/temp/");
        URLClassLoader uCL1 = new URLClassLoader(new URL[]{url});
        Class whiteshipClass1 = uCL1.loadClass("Whiteship");
        Object whiteship1 = whiteshipClass1.newInstance();

        URLClassLoader uCL2 = new URLClassLoader(new URL[]{url});
        Class whiteshipClass2 = uCL2.loadClass("Whiteship");
        Object whiteship2 = whiteshipClass2.newInstance();

        assertThat(whiteshipClass1, is(not(whiteshipClass2)));
        whiteshipClass1.cast(whiteship2);
    }

이번에는 주관식입니다.

위 테스트는 통과 합니다.왜 통과하는 걸까요? 
즉, 왜 ClassCastException이 발생하는 걸까요?
top