2014-09-20 4 views
0

Java 프로젝트를 컴파일하여 생성 된 클래스 파일 목록을 입력으로 받아들이고 이러한 클래스와 관련된 테스트 케이스를 실행하는 플러그인을 작성했습니다. 클래스 로더를 사용하여 클래스를로드하고 JUnitCore()를 사용하여 테스트 케이스를 실행합니다. 아래의 코드는 잘 작동하며 입력 클래스에 대해 실행될 때 아무런 문제가 없습니다.ClassLoader가 이전 버전의 클래스를로드합니다. - Java

Class<?> clazz = Class.forName(className);  
Request request = Request.aClass(clazz); 
Result result = new JUnitCore().run(request); 

그러나 내 프로그램에서 위의 코드는 유사한 클래스에 대해 수천 번 실행해야합니다. 단순함을 위해서 우리는 단 하나의 클래스 만 가지고 있다고 가정합니다. 클래스가 컴파일 된 후 컴파일러 에러 이없는 경우 플러그인의 bin 디렉토리로 복사 된 후 내 프로그램이 호출되고 모든 테스트 케이스를 통과하는지 확인합니다 .

다음 반복에서는 원래 소스 코드가 자동으로 변경된 다음 컴파일되고 컴파일러 오류가없는 경우 테스트 케이스가 다시 복사됩니다. 이 프로세스는 원하는 결과를 얻기 위해 수천 번 실행될 수 있습니다. [경우에 따라서는 몇 시간]

그러나 클래스 로더는 컴파일러 클래스의 첫 번째 버전을 사용하고 다음 반복에서는 새 버전을로드하지 않고 이전 버전을 계속 사용합니다. 나는 각 추가에서 Thread.sleep (1000)copy 명령 앞에 추가하면 올바른 버전을 찾을 수 있음을 발견했다.

첫째, 내가 왜하지 복사 후 사본 및 전에 일시 정지 이 필요하십니까? 아마도 파일이 클래스 로더가로드하기 전에 파일을 복사하는 동안 finalize되지 않았을 것이라고 예상하고, 클래스 로더는 이전 버전을 사용합니다. 그러나 복사 전에 일시 중지를 추가하면 제대로 작동하고 복사 후 일시 중지를 추가하면 이전 버전이 사용됩니다.

둘째, 내 프로그램에서 수면을 사용하는 것은 좋지 않습니다. 가장 좋은 경우에 내 플러그인은 원하는 결과를 찾기 위해 몇 시간 동안 작동 할 수 있으며 각 반복에서 수면을 추가하려면 결과를 얻는 데 며칠이 걸릴 수 있습니다. 따라서 나는 수면이없는 해결책을 선호합니다. Thread.sleep없이 위의 문제를 어떻게 복사 할 수 있는지 알고 있다면 알려주십시오.

+0

ClassLoader는 실제로 클래스의 "previos"버전을 사용하지 않으며 처음로드 될 때 클래스의 첫 번째 버전을 사용합니다. 클래스가로드 된 경우 새 클래스로 대체되지 않습니다. 새 버전을로드하려면 약간의 마법을 써야합니다. 그리고 그런 질문은 벌써 물었다. 검색을 사용하라. –

+0

[클래스 새로 고침을위한 새 ClassLoader 만들기] 가능한 복제본 (http://stackoverflow.com/questions/9819318/create-new-classloader-to-reload-class) – Joe

+0

수면을 추가하면 올바른 버전이 사용됩니다. – user3601784

답변

0

해결책을 찾았습니다. 사실, 프로그램을 변경 한 후에는 먼저 프로젝트를 새로 고친 다음 파일을 복사합니다. 그러나 문제는 JDT가 복사 전에 인덱스를 다시 컴파일하고 다시 작성하지 않는다는 것입니다. 그래서 재건 작업이 끝나기를 기다렸다가 복사를해야합니다. 복사하기 전에 Thread.sleep이 문제를 해결할 수있는 이유입니다. 그러나 더 좋은 해결책은 프로젝트를 새로 고치는 동안 아래 지침을 사용하는 것입니다.

try { 
     project.refreshLocal(IResource.DEPTH_INFINITE, null); 

     IJobManager jobManager = Job.getJobManager(); 
     jobManager.join(ResourcesPlugin.FAMILY_AUTO_BUILD, null); 
    } catch (CoreException | OperationCanceledException | InterruptedException e) { 
      e.printStackTrace(); 
    } 

위 라인이 문제를 해결합니다.

관련 문제