0

我正在使用 Play Framework 开发 Java 沙盒系统。感谢 Play,我必须处理将要在服务器上上传 jar 文件(可能包含恶意代码)的用户。Play 控制器将 jar 文件上传到“上传”目录并将其加载到我的 Sandbox 中:

public static Result upload(){
        // Get the form
        MultipartFormData body = request().body().asMultipartFormData();

        // Get all files parts
        List<FilePart> fileparts = body.getFiles();

        for(FilePart filepart : fileparts)
        {
            if (filepart != null) {
                String fileName = filepart.getFilename();
                File file = filepart.getFile();
                String pathToJar = Play.application().path() + "/upload/" + fileName;
                file.renameTo(new File(pathToJar));
                // Load the Bot in a sandboxed environment
                Referee.loadJarBot("file:/" + pathToJar);
            }
        }
        // Debug message
        return ok("Uploaded");
    }

这段代码工作得很好。Referee 类将打开 Jar 文件并从该 Jar 中实例化一个 BotSample 类。BotSample 实现了 MyrmesPlayer 接口。

公共类 BotSample 实现 MyrmesPlayer

这是打开 Jar 文件并创建 BotSample 新实例的代码:

public static void loadJarBot(String pathToJar){
        try
        {
            // Load the Jar file
            URL url = new URL(pathToJar);
            URLClassLoader cl = new URLClassLoader(new URL[] { url });


            // Load the bot class
            Class<?> botClass = cl.loadClass("myrmes.bot.app.BotSample");

            /* Problem comes here */
            final MyrmesPlayer myrmesPlayer = (MyrmesPlayer) botClass.newInstance();


            /* ... */

        } 
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

尽管 MyrmesPlayer 在类层次结构中高于 BotSample,但从 BotSample 到 MyrmesPlayer 的转换会引发 ClassCastException,为什么?o_o

    java.lang.ClassCastException: myrmes.bot.app.BotSample cannot be cast to myrmes.
    bot.api.MyrmesPlayer
            at myrmes.referee.app.Referee.loadJarBot(Referee.java:31)
            at controllers.Application.upload(Application.java:40)
            at Routes$$anonfun$routes$1$$anonfun$applyOrElse$3$$anonfun$apply$3.appl
    y(routes_routing.scala:81)
            at Routes$$anonfun$routes$1$$anonfun$applyOrElse$3$$anonfun$apply$3.appl
    y(routes_routing.scala:81)
            at play.core.Router$HandlerInvoker$$anon$6$$anon$2.invocation(Router.sca
    la:164)
            at play.core.Router$Routes$$anon$1.invocation(Router.scala:345)
        at play.core.j.JavaAction$$anon$1.call(JavaAction.scala:31)
        at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:74)
        at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:73)
        at play.libs.F$Promise$PromiseActor.onReceive(F.java:420)
        at akka.actor.UntypedActor$$anonfun$receive$1.applyOrElse(UntypedActor.s
cala:159)
        at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425)
        at akka.actor.ActorCell.invoke(ActorCell.scala:386)
        at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230)
        at akka.dispatch.Mailbox.run(Mailbox.scala:212)
        at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(
AbstractDispatcher.scala:502)
        at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262)
        at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool
.java:975)
        at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:14
78)
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThre
ad.java:104)

此外,如果我在一个独立的应用程序(即没有 Play 的纯 Java)中使用这个 loadJarBot 方法,这个代码就可以完美地工作。

在此先感谢您的帮助

4

2 回答 2

0

我找到了为什么它不起作用。Play 使用的是自己的类加载器,我试图在另一个类加载器调用的实例上强制转换一个类。不同类加载器加载的类是完全不同的。

我必须使用 Java 反射来调用方法,根据:跨类加载器转换?

于 2013-06-18T06:44:40.143 回答
0

对于跨类加载器(或者更确切地说在不同类加载器之间复制对象)进行转换,请查看Transloader library。至于沙盒,你可以看看最近的java-sandbox 项目。请问,你是如何实现你的沙盒的?

于 2013-06-20T18:01:22.233 回答