[SCALA] 동적 스칼라 2.11 런타임에 스칼라 클래스 파일을 컴파일
SCALA동적 스칼라 2.11 런타임에 스칼라 클래스 파일을 컴파일
나는 스칼라 2.10의 작품 스칼라에서 런타임에 외부 클래스를 컴파일하는 다음 코드가
/**
* Compile scala files and keep them loaded in memory
* @param classDir Directory storing the generated scala files
* @throws IOException if there is problem reading the source files
* @return Classloader that contains the compiled external classes
*/
@throws[IOException]
def compileFiles(classDir: String): AbstractFileClassLoader = {
val files = recursiveListFiles(new File(classDir))
.filter(_.getName.endsWith("scala"))
println("Loaded files: \n" + files.mkString("[", ",\n", "]"))
val settings: GenericRunnerSettings = new GenericRunnerSettings(err => println("Interpretor error: " + err))
settings.usejavacp.value = true
val interpreter: IMain = new IMain(settings)
files.foreach(f => {
interpreter.compileSources(new BatchSourceFile(AbstractFile.getFile(f)))
})
interpreter.getInterpreterClassLoader()
}
그리고 다른 곳에서, 나는 예를 들어, 인스턴스화 클래스의 클래스 로더 참조를 사용할 수 있습니다
val personClass = classLoader.findClass("com.example.dynacsv.PersonData")
val ctor = personClass.getDeclaredConstructors()(0)
val instance = ctor.newInstance("Mr", "John", "Doe", 25: java.lang.Integer, 165: java.lang.Integer, 1: java.lang.Integer)
println("Instantiated class: " + instance.getClass.getCanonicalName)
println(instance.toString)
그러나 getInterpreterClassLoader 방법으로 더 이상 작동 위의 scala.tools.nsc.interpreter.IMain에서 제거되었습니다. 또한, AbstractFileClassLoader 이동 및 사용되지 않습니다. 더 이상 외부 패키지에서 클래스 로더에 (때문에) findClass 메소드를 호출 할 수 없습니다.
스칼라 2.11에서 위의 작업을 수행하기 위해 권장되는 방법은 무엇입니까? 감사!
해결법
-
==============================
1.당신의 목표는 런타임에서 외부 스칼라 클래스를 실행하는 경우, 내가 scala.tools.reflect.ToolBox와 평가를 사용하는 것이 좋습니다 것 (그것은 REPL에 포함되어 있지만, 일반적인 사용을 위해 당신은 스칼라 - reflect.jar를 추가해야한다) :
당신의 목표는 런타임에서 외부 스칼라 클래스를 실행하는 경우, 내가 scala.tools.reflect.ToolBox와 평가를 사용하는 것이 좋습니다 것 (그것은 REPL에 포함되어 있지만, 일반적인 사용을 위해 당신은 스칼라 - reflect.jar를 추가해야한다) :
import scala.reflect.runtime.universe import scala.tools.reflect.ToolBox val tb = universe.runtimeMirror(getClass.getClassLoader).mkToolBox() tb.eval(tb.parse("""println("hello!")"""))
또한 tb.compile을 사용하여 파일을 컴파일 할 수 있습니다.
예제를 수정 : 당신이 외부 파일이 있다고 가정
class PersonData() { val field = 42 } scala.reflect.classTag[PersonData].runtimeClass
당신이 그래서
val clazz = tb.compile(tb.parse(src))().asInstanceOf[Class[_]] val ctor = clazz.getDeclaredConstructors()(0) val instance = ctor.newInstance()
추가 가능성있는 (거의) 무제한, 당신은 당신이 원하는대로 전체 트리 AST 작업을 얻을 수 있습니다 :
showRaw(tb.parse(src)) // this is AST of external file sources // this is quasiquote val q""" class $name { ..$stats } scala.reflect.classTag[PersonData].runtimeClass """ = tb.parse(src) // name: reflect.runtime.universe.TypeName = PersonData // stats: List[reflect.runtime.universe.Tree] = List(val field = 42) println(name) // PersonData
이 트릭에 대한 공식 문서를 참조하십시오 :
http://docs.scala-lang.org/overviews/reflection/symbols-trees-types.html
http://docs.scala-lang.org/overviews/quasiquotes/intro.html
from https://stackoverflow.com/questions/39137175/dynamically-compiling-scala-class-files-at-runtime-in-scala-2-11 by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] 스칼라 2.10에서 문자열 보간 - 어떻게 문자열 변수를 보간하는? (0) | 2019.11.16 |
---|---|
[SCALA] 어떻게 스칼라 mutable.Map에 immutable.Map을 변환 할 수 있습니까? (0) | 2019.11.16 |
[SCALA] 밀봉 특성의 서브 클래스를 얻기 (0) | 2019.11.16 |
[SCALA] 어셈블리 병합-전략 문제 SBT-어셈블리를 사용 (0) | 2019.11.16 |
[SCALA] 왜 정적 방법은 좋은 OO 연습 간주됩니다? [닫은] (0) | 2019.11.16 |