简体   繁体   English

无法在Java接口上强制转换

[英]Unsolvable cast on Java interface

I'm working on a Java Sandboxing system with Play Framework. 我正在使用Play Framework开发Java沙箱系统。 I've to deal with users who are going to upload a jar file (which can contain malicious code) on a server thanks to Play. 由于要玩Play,我不得不与要在服务器上上传jar文件(其中可能包含恶意代码)的用户打交道。 The Play controller uploads the jar file in a "upload" directory and loads it into my Sandbox : 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");
    }

This code works pretty well. 这段代码效果很好。 The Referee class will open the Jar file and instanciate a BotSample class from this Jar. Referee类将打开Jar文件,并从该Jar实例化BotSample类。 BotSample implements a MyrmesPlayer interface. BotSample实现了MyrmesPlayer接口。

public class BotSample implements MyrmesPlayer 公共类BotSample实现MyrmesPlayer

Here's the code which open the Jar file and create a new instance of BotSample : 这是打开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();
        }
    }

The cast from BotSample to MyrmesPlayer throws a ClassCastException although MyrmesPlayer is higher than BotSample in the class hierarchy, why ? 尽管MyrmesPlayer在类层次结构中高于BotSample,但从BotSample到MyrmesPlayer的转换会引发ClassCastException。 O_o 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)

Moreover, if I use this loadJarBot method in a standalone application (ie pure Java without Play), this code works perfectly. 而且,如果我在独立的应用程序(即不带Play的纯Java)中使用此loadJarBot方法,则此代码可以完美运行。

Thanks in advance for your help 在此先感谢您的帮助

I've found why it didn't work. 我发现了为什么它不起作用。 Play uses is own Classloader and i tried to cast a class on an instance called by an other Classloader. Play使用的是自己的Classloader,我尝试在另一个Classloader调用的实例上强制转换一个类。 Classes loaded by different classloaders are completly differents. 由不同的类加载器加载的类完全不同。

I've to use Java Reflection to call methods according to : cast across classloader? 我必须使用Java Reflection来根据以下方法调用方法: 跨类加载器投射?

For casting across classloader (or rather replicating objects between different classloaders) have a look at the Transloader library . 要在类加载器之间进行转换(或在不同的类加载器之间复制对象),请查看Transloader库 As for sandboxing, you might take a look at the recent java-sandbox project . 至于沙箱,您可以看一下最近的java-sandbox项目 May I ask, how you implemented your sandbox? 请问您如何实施沙盒?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM