【问题标题】:Scala URLClassLoader is not reloading class fileScala URLClassLoader 没有重新加载类文件
【发布时间】:2018-12-11 19:48:33
【问题描述】:

我正在运行一个需要执行一些规则的 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

【问题讨论】:

    标签: java scala akka


    【解决方案1】:
    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 方法。如果 parent 为 null,则使用虚拟机内置的类加载器。

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

    要重新加载一个类,您必须实现自己的 ClassLoader 子类,如link

    【讨论】:

    • 但是 OP 正在为每个请求创建一个新的 CL。那么加载的类缓存在哪里呢?
    • ClassLoader 类使用委托模型来搜索类和资源。 ClassLoader 的每个实例都有一个关联的父类加载器。当请求查找类或资源时,ClassLoader 实例将在尝试查找类或资源本身之前将对该类或资源的搜索委托给其父类加载器。
    • 但据我了解,父类加载器不知道这个类。只有 OP 创建的类加载器(如果不是真的,那可能是问题的原因)。除非父类加载器以某种方式缓存其子类的类?
    • 这似乎与我所说的没有矛盾,还是我遗漏了什么?
    猜你喜欢
    • 1970-01-01
    • 2015-12-22
    • 2014-09-01
    • 1970-01-01
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-02
    相关资源
    最近更新 更多