gpt4 book ai didi

java - Scala URLClassLoader 未重新加载类文件

转载 作者:太空宇宙 更新时间:2023-11-04 09:59:09 24 4
gpt4 key购买 nike

我正在运行一个 scala 项目,我需要在其中执行一些规则。这些规则将在运行时动态添加或从 scala 类文件中删除。

所以,我希望每当规则类修改时,它都应该重新加载以获取更改而不停止执行过程。

我使用runtime.getruntime.exec()来编译它

并且是 URL 类加载器,用于从类中获取修改后的代码

exec() 运行罚款。即使我使用 URL 类加载器,目标文件夹中的类也会被修改,也不会出现任何错误。

但它给了我与项目启动时相同的结果。它没有给我修改代码。

下面是我正在使用的代码。

package RuleEngine

import akka.actor._
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import akka.util.Timeout

import scala.io.StdIn
import Executor.Compute
import scala.concurrent.{Await, ExecutionContextExecutor}
import scala.concurrent.duration._


object StatsEngine {

def main(args: Array[String]) {

implicit val system: ActorSystem = ActorSystem("StatsEngine")
implicit val materializer: ActorMaterializer = ActorMaterializer()
implicit val executionContext: ExecutionContextExecutor = system.dispatcher

implicit val timeout = Timeout(10 seconds)
val computeDataActor = system.actorOf(Props[Compute],"ComputeData")


val route = {
post {
path("computedata"/) {
computeDataActor ! "Execute"
complete("done")
}
}
}


val bindingFuture = Http().bindAndHandle(route , "localhost", 9000)

println(s"Server online at http://localhost:9000/\nPress RETURN to stop...")
}
}

这是我创建 Akka HTTP 来制作 API 的主要对象文件

它将调用computeDataActor,其代码如下。

package Executor

import java.io.File
import java.net.URLClassLoader

import CompiledRules.RulesList
import akka.actor.Actor

class Compute extends Actor{

def exceuteRule(): Unit ={
val rlObj = new RulesList
rlObj.getClass.getDeclaredMethods.map(name=>name).foreach(println)

val prcs = Runtime.getRuntime().exec("scalac /home/hduser/MStatsEngine/Test/RuleListCollection/src/main/scala/CompiledRules/RuleList.scala -d /home/hduser/MStatsEngine/Test/RuleListCollection/target/scala-2.11/classes/")
prcs.waitFor()

val fk = new File("/home/hduser/MStatsEngine/Test/RuleListCollection/target/scala-2.11/classes/").toURI.toURL

val classLoaderUrls = Array(fk)

val urlClassLoader = new URLClassLoader(classLoaderUrls)

val beanClass = urlClassLoader.loadClass("CompiledRules.RulesList")

val constructor = beanClass.getConstructor()

val beanObj = constructor.newInstance()

beanClass.getDeclaredMethods.map(x=>x.getName).foreach(println)

}
override def receive: Receive ={
case key:String => {
exceuteRule()
}
}
}

规则已导入,如下所述。

package CompiledRules

class RulesList{

def R1 : Any = {
return "executing R1"
}

def R2 : Any = {return "executing R2"}
// def R3 : Any = {return "executing R3"}
//def R4 : Any = {return "executing R4"}
def R5 : Any = {return "executing R5"}
}//Replace

因此,当我执行代码并调用 API 时,我将得到输出

R1
R2
R5

现在,在不停止项目的情况下,我将取消注释 R3 和 R4。我会再次调用API,当我再次执行代码时,使用

runtime.getruntime.exec()

它将编译文件并更新目标中的类

因此,我使用 URLClassLoader 来获取修改代码的新对象。

但不幸的是,我总是得到与项目启动时相同的结果

R1
R2
R5

以下是完整项目的链接 Source Code

最佳答案

val beanClass = urlClassLoader.loadClass("CompiledRules.RulesList")
val constructor = beanClass.getConstructor()
val beanObj = constructor.newInstance()

只是创建已加载类的 newInstance。

Java 的内置类加载器在加载类之前总是检查类是否已经加载。 loadClass

protected Class<?> loadClass(String name,
boolean resolve)
throws ClassNotFoundException

加载具有指定二进制名称的类。此方法的默认实现按以下顺序搜索类:调用 findLoadedClass(String) 检查该类是否已加载。

调用父类加载器的loadClass方法。如果父级为 null,则使用虚拟机内置的类加载器。

调用 findClass(String) 方法来查找类。

要重新加载类,您必须实现自己的 ClassLoader 子类,如 link 所示。

关于java - Scala URLClassLoader 未重新加载类文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53722535/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com