2

So I've come across this problem. We're using Java as our 'scripting' language, because we already use it for everything else, and it doesn't require any additional 3rd party libs.

Now currently we're executing runtime code via reflection. Something like:

Class triggerAction = null;
    try {
        triggerAction = Class.forName(actionName);
        Gdx.app.log("Info", triggerAction.getName() + " attached to "
                + this.toString());
        try {
            this.triggerAction = (TriggerAction) triggerAction
                    .newInstance();
        } 

This is great, but it's not ideal. Any java files that are meant to be run at runtime must still be compiled into the latest build. Ideally, non developers could play with script files stored in like a '/scripts/' dir, and then just run the program and have the modified .java file execute. This is something I've never done before, so I'm a little at a loss as to how to go about it in a way that will be safe for the enduser.

I've found this approach: Generating, compiling and using Java code at run time?

But I'm not expecting most end users to have PATH setup and all that, so I'm concerned that these solutions could run into problems there. What's the ideal approach here?

Community
  • 1
  • 1
Scuba Steve
  • 1,541
  • 1
  • 19
  • 47
  • 3
    *We're using Java as our 'scripting' language* Wait, what? Java is definitely NO scripting language. If you want to use a scripting language, use JavaScript. With Java 8, you get a full java-implemented version of a JavaScript engine called [Nashorn](http://www.oracle.com/technetwork/articles/java/jf14-nashorn-2126515.html), which you can call from within Java. Otherwise, you can load classes at runtime, but this is more complicated, since you have to create a plugin system and [use a class loader](http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html). – Turing85 Jun 21 '15 at 00:50
  • So your question is "how can I compile a Java source file at runtime?"? – user253751 Jun 21 '15 at 00:59
  • I did not know about Nashorn. This is interesting. But how can I interface between the scripts and my java codebase? – Scuba Steve Jun 21 '15 at 02:24
  • I answered my own question. But yeah this looks like the direction we'll go. Thanks Turing85. See the "Invoking Java methods from JS" section. http://winterbe.com/posts/2014/04/05/java8-nashorn-tutorial/ – Scuba Steve Jun 21 '15 at 02:41
  • Turing85, if you wanted to go ahead and post your answer below, that's the approach I ended up taking. – Scuba Steve Jun 24 '15 at 16:00

3 Answers3

0

Use Runtime.getRuntime().exec("javac SomeFile.java") to compile the Java files via the command line.

If you're not sure if javac or java is in the PATH, try specifying the fully path directly (i.e. C:\Program Files\Java\jdk1.8.0_xx\bin\javac) or just ask the user where it is.

James Ko
  • 32,215
  • 30
  • 128
  • 239
0

But I'm not expecting most end users to have PATH setup and all that, so I'm concerned that these solutions could run into problems there.

Using the javax.tools approach (described in the Q&A you linked to) does not require the user to set $PATH or $JAVA_HOME or $CLASS_PATH. AFAIK, all it requires is that the user is running java from a JDK install.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Hmm ok. Could be doable with a launch4j wrapper. Dunno about the legal stuff around re-distributing the JDK though. – Scuba Steve Jun 21 '15 at 02:08
  • The legal issues are the same as for a JRE. (But if you are in doubt, talk to your company lawyer.) Besides, you don't need a special wrapper. Your Java application can run the Java compiler in the same JVM. – Stephen C Jun 21 '15 at 02:48
  • Not if the end user isn't using a JDK, right? That's a pretty big problem for us. So use launch4j to wrap a JDK, at least that makes sense to me, minus the potential legal issues. – Scuba Steve Jun 21 '15 at 03:24
  • So what is the difference between not having a JDK installed, and not having a JRE installed? Really, you that your requirement to use launch4j is independent of your dynamic compilation requirement. – Stephen C Jun 21 '15 at 13:02
  • Because, like I said, endusers don't tend to install JDKs on their machines. – Scuba Steve Jun 21 '15 at 23:43
  • End users don't tend to install JREs on their machines either. Don't you get it yet? 1) If you can get an end user to install a JRE, you can get them to install a JDK. 2) If you can't get them to install a JDK, you can't get them to install a JRE either. 3) No mainstream OS installs a JRE by default these days, so you can't rely on it being there. 4) Ergo, if you need a wrapper, then you need it in *both* cases. – Stephen C Jun 23 '15 at 12:16
  • The attitude is so thick I could cut it with a knife. Conversation over. – Scuba Steve Jun 24 '15 at 16:00
0

Ended up using the Nashorn JS engine for Java. Worked like a charm! No build-time workflows needed for script changes.

Scuba Steve
  • 1,541
  • 1
  • 19
  • 47