2017-01-19 5 views
1

내가 코 틀린 클래스 다시로드 실험있어 객체하지만 최근에이 가까이에 뭔가 붙어있어 :코 틀린 클래스/기능

package com.aurieh.reloading 
fun doSomething(): String { // a function that does not belong to the class, 
    // so it gets compiled as FileName$doSomething$... 
} 

class FileName { 
    // do things with doSomething 
} 

을 내가 (ImplClassLoader.defineClassByteArray로)이 클래스를 다시로드하는 경우 그리고 내가 유사한 오류 얻을, 내부적으로 해봐요 전화 메소드를 호출 할 시도 : 리로드 클래스 해봐요은 첨부하지 않는 것처럼 나는이 해석 할

java.lang.IllegalAccessError: tried to access method com.aurieh.reloading.FileName.doSomething$default()Ljava/lang/String; from class com.aurieh.ares.reloading.FileName` 

을 .. 그래서 내 질문이 될 것이다, 어떻게 이 오류를 해결할 수 있습니까? 어떻게 든 클래스 로더를 다시로드하는 것에 무언가를 붙이는 것에 의해? 참고로

, 내 클래스 다시로드 코드 :

class Reloader : ClassLoader() { 
    fun load(name: String, bytes: ByteArray, offset: Int, len: Int): Class<*> { 
     return defineClass("com.aurieh.reloading.$name", bytes, offset, len) 
    } 
} 

그리고 로딩

:

val bytes = File("../classes/path/to/class/FileName.class").readBytes() 
Reloader().load("FileName", bytes, 0, bytes.size).newInstance() 

답변

4

기본적으로 최상위 기능은 파일에 정의 된 클래스의 컴파일되지 않습니다. 대신 최상위 수준 멤버 인 별개의 클래스 인 FileNameKt (파일 이름이 FileName.kt 인 경우)이 만들어집니다.

그래서, (즉, 어떤 불만 링크없이) 제대로 클래스로드를 만들기 위해, 먼저 FileNameKt 클래스를로드 할 수있다 : 나는 그것으로 또 다른 문제가 있지만

val bytes1 = File("../classes/path/to/class/FileNameKt.class").readBytes() 
val bytes2 = File("../classes/path/to/class/FileName.class").readBytes() 
val reloader = Reloader() 
reloader.load("FileNameKt", bytes1, 0, bytes1.size) 
reloader.load("FileName", bytes2, 0, bytes2.size).newInstance() 
+0

아, 감사합니다 .. 당신이 만약 클래스 메서드 함수에서 lambda를 사용하면 FileName $ method_lambda_is_being_called_in $ number_of_lambda.class로 컴파일됩니다. 방법이 있다면 내가 동적으로 그것들을 체크하고로드 할 것인가? – Aurieh

+0

@Aurieh, 당신은 당신의'ClassLoader' 구현에서'loadClass'와 같은 것을 무효화시켜야 할 것 같습니다. 람다를 사용하는 함수가 호출되면,'name'' com.example.FileName $ f $ x $ 1'을 갖는'loadClass (name : String?)'에 대한 호출, 즉 람다 클래스 이름이 보입니다. 이것은 클래스 경로의 개념에 더 가깝습니다 : 클래스 로더가 이름으로 특정 경로의 클래스를로드 할 수있게하고 클래스가 처음 사용되면 구현에서로드합니다. – hotkey

+0

아, 현재 현재 그 경로에있는 모든 클래스를 살펴보고 클래스 이름과 $로 시작하는지 확인한 후 실행 중입니다. 내 말은 작동하지만 슈퍼가 더러운 것입니다. 당신의 방법을 구현할 수있는 방법을 살펴보십시오. 하지만 지금은 대답으로 표시하고 있습니다. 감사합니다! – Aurieh