I'm using Java 8 Nashorn to render CommonMark to HTML server side. If I compile and cache and reuse a CompiledScript, a certain page takes 5 minutes to render. However, if I instead use eval, and cache and reuse the script engine, rendering the same page takes 3 seconds.
Why is CompiledScript so slow? (sample code follows)
What's a good approach for running Javascript code in Nashorn, over and over again as quickly as possible? And avoiding compiling the Javascript code more than once?
This is the server side Scala code snippet that calls Nashorn in a way that takes 5 minutes: (when run 200 times; I'm compiling many comments from CommonMark to HTML.) (This code is based on this blog article.)
if (engine == null) {
val script = scala.io.Source.fromFile("public/res/remarkable.min.js").mkString
engine = new js.ScriptEngineManager(null).getEngineByName("nashorn")
compiledScript = engine.asInstanceOf[js.Compilable].compile(s"""
var global = this;
$script;
remarkable = new Remarkable({});
remarkable.render(__source__);""");
}
engine.put("__source__", "**bold**")
val htmlText = compiledScript.eval()
Edit Note that the $script above is reevaluated 200 times. I did test a version that evaluated it only once, but apparently then I wrote some bug, because the only-once version wasn't faster than 5 minutes, although it should have been one of the fastest ones, see Halfbit's answer. Here's the fast version:
...
val newCompiledScript = newEngine.asInstanceOf[js.Compilable].compile(s"""
var global;
var remarkable;
if (!remarkable) {
global = this;
$script;
remarkable = new Remarkable({});
}
remarkable.render(__source__);""")
...
/Edit
Whereas this takes 2.7 seconds: (when run 200 times)
if (engine == null) {
engine = new js.ScriptEngineManager(null).getEngineByName("nashorn")
engine.eval("var global = this;")
engine.eval(new jio.FileReader("public/res/remarkable.min.js"))
engine.eval("remarkable = new Remarkable({});")
}
engine.put("source", "**bold**")
val htmlText = engine.eval("remarkable.render(source)")
I would actually have guessed that the CompiledScript version (the topmost snippet) would have been faster. Anyway, I suppose I'll have to cache the rendered HTML server side.
(Linux Mint 17 & Java 8 u20)
Update:
I just noticed that using invokeFunction at the end instead of eval is almost twice as fast, takes only 1.7 seconds. This is roughly as fast as my Java 7 version that used Javascript code compiled by Rhino to Java bytecode (as a separate and complicated step in the build process). Perhaps this is as fast as it can get?
if (engine == null) {
engine = new js.ScriptEngineManager(null).getEngineByName("nashorn")
engine.eval("var global = this;")
engine.eval(new jio.FileReader("public/res/remarkable.min.js"))
engine.eval("remarkable = new Remarkable({});")
engine.eval(
"function renderCommonMark(source) { return remarkable.render(source); }")
}
val htmlText = engine.asInstanceOf[js.Invocable].invokeFunction(
"renderCommonMark", "**bold1**")
The variant of your code which uses CompiledScript seems to re-evaluate remarkable.min.js 200 times - while your eval based version does this once. This explains the huge difference in runtimes.
With just the remarkable.render(__source__) precompiled, the CompiledScript based variant is slightly faster than the eval and invokeFunction based ones (on my machine, Oracle Java 8u25).
CompiledScript has been improved a bit in 8u40. You can download early access download of jdk8u40 # https://jdk8.java.net/download.html
Related
I'm using Groovy to execute some piece of Java code.
For my purpose Groovy it's easy to use since the code I have to execute has an arbitrary number of params that I cannot predict, since it depends on the user input.
The input I'm talking about is OWL axioms, that are nested.
This is my code:
//The reflection
static void reflectionToOwl() {
Binding binding = new Binding(); //155 ms
GroovyShell shell = new GroovyShell(binding);
while (!OWLMapping.axiomStack.isEmpty()) {
String s = OWLMapping.axiomStack.pop();
shell.evaluate(s); //350 ms
}
}
The only bottleneck in my program is exactly here. More is the data I have to process more is the ms I have to wait for.
Do you have any suggestions?
If you need to increase Groovy performance, you can use #CompileStatic annotation.
This will let the Groovy compiler use compile time checks in the style of Java then perform static compilation, thus bypassing the Groovy meta object protocol.
Just annotate specific method with it. But be sure that you don't use any dynamic features in that scope.
As an example:
import groovy.transform.CompileStatic
#CompileStatic
class Static {
}
class Dynamic {
}
println Static.declaredMethods.length
Static.declaredMethods.collect { it.name }.each { println it }
println('-' * 100)
println Dynamic.declaredMethods.length
Dynamic.declaredMethods.collect{ it.name }.each { println it }
Won't generate some extra methods:
6
invokeMethod
getMetaClass
setMetaClass
$getStaticMetaClass
setProperty
getProperty
8
invokeMethod
getMetaClass
setMetaClass
$getStaticMetaClass
$getCallSiteArray
$createCallSiteArray
setProperty
getProperty
Like the first answer indicated, #CompileStatic would have been the first option on my list of tricks as well.
Depending on your use case, pre-parsing the script expressions and calling 'run' on them execution time might be an option here. The following code demonstrates the idea:
def exprs = [
"(1..10).sum()",
"[1,2,3].max()"
]
def shell = new GroovyShell()
def scripts = time("parse exprs") {
exprs.collect { expr ->
shell.parse(expr) // here we pre-parse the strings to groovy Script instances
}
}
def standardBindings = [someKey: 'someValue', someOtherKey: 'someOtherValue']
scripts.eachWithIndex { script, i ->
time("run $i") {
script.binding = new Binding(standardBindings)
def result = script.run() // execute the pre-parsed Script instance
}
}
// just a small method for timing operations
def time(str, closure) {
def start = System.currentTimeMillis()
def result = closure()
def delta = System.currentTimeMillis() - start
println "$str took $delta ms -> result $result"
result
}
which prints:
parse exprs took 23 ms -> result [Script1#1165b38, Script2#4c12331b]
run 0 took 7 ms -> result 55
run 1 took 1 ms -> result 3
on my admittedly aging laptop.
The above code operates in two steps:
parse the String expressions into Script instances using shell.parse. This can be done in a background thread, on startup or otherwise while the user is not waiting for results.
"execution time" we call script.run() on the pre-parsed script instances. This should be faster than calling shell.evaluate.
The takeaway here is that if your use case allows for pre-parsing and has a need for runtime execution speed, it's possible to get quite decent performance with this pattern.
An example application I have used this in is a generic feed file import process where the expressions were customer editable data mapping expressions and the data was millions of lines of product data. You parse the expressions once and call script.run millions of times. In this kind of scenario pre-parsing saves a lot of cycles.
Insted of Groovy you can also use BeanShell.
It is supereasy to use and it is very light:
Website
Probably not all Java function are supported, but just give a try.
What's the easiest way to execute a Python script from Java, and receive the output of that script? I've looked for different libraries like Jepp or Jython, but most appear out of date. Another problem with the libraries is that I need to be able to easily include a library with the source code (though I don't need to source for the library itself) if I use a library.
Because of this, would the easiest/most effective way be to simply do something like call the script with runtime.exec, and then somehow capture printed output? Or, even though it would be very painful for me, I could also just have the Python script output to a temporary text file, then read the file in Java.
Note: the actual communication between Java and Python is not a requirement of the problem I am trying to solve. This is, however, the only way I can think of to easily perform what needs to be done.
Not sure if I understand your question correctly, but provided that you can call the Python executable from the console and just want to capture its output in Java, you can use the exec() method in the Java Runtime class.
Process p = Runtime.getRuntime().exec("python yourapp.py");
You can read up on how to actually read the output from this resource:
http://www.devdaily.com/java/edu/pj/pj010016
import java.io.*;
public class JavaRunCommand {
public static void main(String args[]) {
String s = null;
try {
// run the Unix "ps -ef" command
// using the Runtime exec method:
Process p = Runtime.getRuntime().exec("ps -ef");
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
}
There is also an Apache library (the Apache exec project) that can help you with this. You can read more about it here:
http://www.devdaily.com/java/java-exec-processbuilder-process-1
http://commons.apache.org/exec/
You can include the Jython library in your Java Project. You can download the source code from the Jython project itself.
Jython does offers support for JSR-223 which basically lets you run a Python script from Java.
You can use a ScriptContext to configure where you want to send your output of the execution.
For instance, let's suppose you have the following Python script in a file named numbers.py:
for i in range(1,10):
print(i)
So, you can run it from Java as follows:
public static void main(String[] args) throws ScriptException, IOException {
StringWriter writer = new StringWriter(); //ouput will be stored here
ScriptEngineManager manager = new ScriptEngineManager();
ScriptContext context = new SimpleScriptContext();
context.setWriter(writer); //configures output redirection
ScriptEngine engine = manager.getEngineByName("python");
engine.eval(new FileReader("numbers.py"), context);
System.out.println(writer.toString());
}
And the output will be:
1
2
3
4
5
6
7
8
9
As long as your Python script is compatible with Python 2.5 you will not have any problems running this with Jython.
I met the same problem before, also read the answers here, but doesn't found any satisfy solution can balance the compatibility, performance and well format output, the Jython can't work with extend C packages and slower than CPython. So finally I decided to invent the wheel myself, it took my 5 nights, I hope it can help you too: jpserve(https://github.com/johnhuang-cn/jpserve).
JPserve provides a simple way to call Python and exchange the result by well format JSON, few performance loss. The following is the sample code.
At first, start jpserve on Python side
>>> from jpserve.jpserve import JPServe
>>> serve = JPServe(("localhost", 8888))
>>> serve.start()
INFO:JPServe:JPServe starting...
INFO:JPServe:JPServe listening in localhost 8888
Then call Python from JAVA side:
PyServeContext.init("localhost", 8888);
PyExecutor executor = PyServeContext.getExecutor();
script = "a = 2\n"
+ "b = 3\n"
+ "_result_ = a * b";
PyResult rs = executor.exec(script);
System.out.println("Result: " + rs.getResult());
---
Result: 6
Jep is anther option. It embeds CPython in Java through JNI.
import jep.Jep;
//...
try(Jep jep = new Jep(false)) {
jep.eval("s = 'hello world'");
jep.eval("print(s)");
jep.eval("a = 1 + 2");
Long a = (Long) jep.getValue("a");
}
I've looked for different libraries like Jepp or Jython, but most seem to be very out of date.
Jython is not "a library"; it's an implementation of the Python language on top of the Java Virtual Machine. It is definitely not out of date; the most recent release was Feb. 24 of this year. It implements Python 2.5, which means you will be missing a couple of more recent features, but it is honestly not much different from 2.7.
Note: the actual communication between Java and Python is not a requirement of the aforementioned assignment, so this isn't doing my homework for me. This is, however, the only way I can think of to easily perform what needs to be done.
This seems extremely unlikely for a school assignment. Please tell us more about what you're really trying to do. Usually, school assignments specify exactly what languages you'll be using for what, and I've never heard of one that involved more than one language at all. If it did, they'd tell you if you needed to set up this kind of communication, and how they intended you to do it.
Jython approach
Java is supposed to be platform independent, and to call a native application (like python) isn't very platform independent.
There is a version of Python (Jython) which is written in Java, which allow us to embed Python in our Java programs. As usually, when you are going to use external libraries, one hurdle is to compile and to run it correctly, therefore we go through the process of building and running a simple Java program with Jython.
We start by getting hold of jython jar file:
https://www.jython.org/download.html
I copied jython-2.5.3.jar to the directory where my Java program was going to be. Then I typed in the following program, which do the same as the previous two; take two numbers, sends them to python, which adds them, then python returns it back to our Java program, where the number is outputted to the screen:
import org.python.util.PythonInterpreter;
import org.python.core.*;
class test3{
public static void main(String a[]){
PythonInterpreter python = new PythonInterpreter();
int number1 = 10;
int number2 = 32;
python.set("number1", new PyInteger(number1));
python.set("number2", new PyInteger(number2));
python.exec("number3 = number1+number2");
PyObject number3 = python.get("number3");
System.out.println("val : "+number3.toString());
}
}
I call this file "test3.java", save it, and do the following to compile it:
javac -classpath jython-2.5.3.jar test3.java
The next step is to try to run it, which I do the following way:
java -classpath jython-2.5.3.jar:. test3
Now, this allows us to use Python from Java, in a platform independent manner. It is kind of slow. Still, it's kind of cool, that it is a Python interpreter written in Java.
ProcessBuilder is very easy to use.
ProcessBuilder pb = new ProcessBuilder("python","Your python file",""+Command line arguments if any);
Process p = pb.start();
This should call python. Refer to the process approach here for full example!
https://bytes.com/topic/python/insights/949995-three-ways-run-python-programs-java
You can try using groovy. It runs on the JVM and it comes with great support for running external processes and extracting the output:
http://groovy.codehaus.org/Executing+External+Processes+From+Groovy
You can see in this code taken from the same link how groovy makes it easy to get the status of the process:
println "return code: ${ proc.exitValue()}"
println "stderr: ${proc.err.text}"
println "stdout: ${proc.in.text}" // *out* from the external program is *in* for groovy
First I would recommend to use ProcessBuilder ( since 1.5 )
Simple usage is described here
https://stackoverflow.com/a/14483787
For more complex example refer to
http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html
I've encountered problem when launching Python script from Java, script
was producing too much output to standard out and everything went bad.
The best way to achieve would be to use Apache Commons Exec as I use it for production without problems even for Java 8 environment because of the fact that it lets you execute any external process (including python, bash etc) in synchronous and asynchronous way by using watchdogs.
CommandLine cmdLine = new CommandLine("python");
cmdLine.addArgument("/my/python/script/script.py");
DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);
Executor executor = new DefaultExecutor();
executor.setExitValue(1);
executor.setWatchdog(watchdog);
executor.execute(cmdLine, resultHandler);
// some time later the result handler callback was invoked so we
// can safely request the exit value
resultHandler.waitFor();
Complete source code for a small but complete POC is shared here that addresses another concern in this post;
https://github.com/raohammad/externalprocessfromjava.git
I am making a function that compares two pictures if they are the same. I have this code:
var rez = null;
rez = compareImages();
alert(rez);
boolean
function compareImages() {
BufferedImage bi1 = java.ImageIO.read(new File("C:\\MyFiles\\pic1.png")),
bi2 = java.ImageIO.read(new File("C:\\MyFiles\\pic2.png"));
Raster r1 = bi1.getData(),
r2 = bi2.getData();
DataBuffer db1 = r1.getDataBuffer(),
db2 = r2.getDataBuffer();
int size1 = db1.getSize(),
size2 = db2.getSize();
// checking if the files sizes are the same
if (size1 != size2)
return false;
// pixel by pixel check up
for (int i = 0; i < size1; i++)
if (db1.getElem(i) != db2.getElem(i))
return false;
return true;
}
Now I want to run this code in .js file but when I do I get an error, missing ";" error. So how do I make this function javascript compatible ?
Thanks.
Unfortunately Javacript and Java are completely seperate languages, and the only thing which they have in common in the name, therefore this is impossible.
If you want to learn about doing something similar in javascript then take a look at the File API's: https://developer.mozilla.org/en-US/docs/DOM/File_APIs
You can't run Java code in JavaScript. You can either compile your Java code as an applet and embed that in you page, or you just rewrite your code in JS. If you use the html5 canvas and the getImageData() function, this should be doable. That way you can easily interact with your code from JavaScript.
It is somewhat possible to use Java classes and APIs in code that you write in JavaScript with Mozilla Rhino.
Rhino is simply a JS interpret written in Java that is bundled with the JDK. It basically allows you to use the Java APIs with JS syntax, but on the other hand, there is no DOM API available and you can't run such scripts in a Web browser. They are run by the JVM.
Is it possible to use JavaScript in Android?? if so, how? Please provide some examples.
Thanks.
I am way late to the party here, but I had this exact need. iOS 7 now includes JavaScriptCore
natively and it is really easy to use (despite limited documentation). The problem is that
I didn't want to use it unless I could also use something similar on Android. So I created the AndroidJSCore project. It allows you to use your JavaScript code natively in Android without requiring a bulky WebView and injection. You can also seamlessly make asynchronous
calls between Java and Javascript.
Update 27 Mar 17: AndroidJSCore has been deprecated in favor of LiquidCore. LiquidCore is based on V8 rather than JavascriptCore, but works essentially same. See the documentation on using LiquidCore as a raw Javascript engine.
From the documentation:
... to get started, you need to create a JavaScript JSContext. The execution of JS code
occurs within this context, and separate contexts are isolated virtual machines which
do not interact with each other.
JSContext context = new JSContext();
This context is itself a JavaScript object. And as such, you can get and set its properties.
Since this is the global JavaScript object, these properties will be in the top-level
context for all subsequent code in the environment.
context.property("a", 5);
JSValue aValue = context.property("a");
double a = aValue.toNumber();
DecimalFormat df = new DecimalFormat(".#");
System.out.println(df.format(a)); // 5.0
You can also run JavaScript code in the context:
context.evaluateScript("a = 10");
JSValue newAValue = context.property("a");
System.out.println(df.format(newAValue.toNumber())); // 10.0
String script =
"function factorial(x) { var f = 1; for(; x > 1; x--) f *= x; return f; }\n" +
"var fact_a = factorial(a);\n";
context.evaluateScript(script);
JSValue fact_a = context.property("fact_a");
System.out.println(df.format(fact_a.toNumber())); // 3628800.0
You can also write functions in Java, but expose them to JavaScript:
JSFunction factorial = new JSFunction(context,"factorial") {
public Integer factorial(Integer x) {
int factorial = 1;
for (; x > 1; x--) {
factorial *= x;
}
return factorial;
}
};
This creates a JavaScript function that will call the Java method factorial when
called from JavaScript. It can then be passed to the JavaScript VM:
context.property("factorial", factorial);
context.evaluateScript("var f = factorial(10);")
JSValue f = context.property("f");
System.out.println(df.format(f.toNumber())); // 3628800.0
Do you mean something like making a native app using Javascript? I know there are tools like Titanium Mobile that let you make native apps using web tools/languages.
You could also make Web Apps. There are loads of resources and tutorials out there for that. Just search "Android Web App tutorial" or something similar.
Yes you can, just create a wrap up code that points to html page and includes your javascript and css.
There are different libraries that can help you with this:
http://www.phonegap.com/
http://www.sencha.com/products/touch/
http://jquerymobile.com/
Just posting this for posterity but React Native is a great solution in this space. You can write a complete app in JS using native views under the hood, or embed a JS component inside an existing Java app. https://reactnative.dev/
How can I use java to get a js file located on a web server, then execute the function in the js file and get the result and use the result in java.
Can you guys give me some code snippet? Great thanks.
You can use the scripting engine built into Java:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public static void main(String[] args) throws Exception {
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
Object result = engine.eval("my-java-script-code")
System.out.println("Result returned by Javascript is: " + result);
}
Here is a more elaborate example.
There's three steps to this process:
Fetch the JS file from the server.
Execute some JS function from the file.
Extract the result.
The first step is fairly simple, there are lots of HTTP libraries in Java that will do this - you effectively want to emulate the simple functionality of something like wget or curl. The exact manner in which you do this will vary depending on what format you want the JS file in for the next step, but the process to get hold of the byte stream is straightforward.
The second step will require executing the JS in a Javascript engine. Java itself cannot interpret Javascript, so you'd need to obtain an engine to run it in - Rhino is a common choice for this. Since you'd need to run this outside of Java, you'll likely have to spawn a process for execution in Rhino using ProcessBuilder. Additionally, depending on the format of the Javascript you might need to create your own "wrapper" javascript that functions like a main class in Java and calls the method in question.
Finally you need to get the result out - obviously you don't have direct access to JavaScript objects from your Java program. The easiest way is going to be for the JS program to print the result to standard out (possibly serialising as something like JSON depending on the complexity of the object), which is being streamed directly to your Java app due to the way you launched the Rhino process. This could be another job for your JS wrapper script, if any. Otherwise, if the JS function has observable side effects (creates a file/modifies a database) then you'll be able to query those directly from Java.
Job done.
I hope you realise this question is far too vague to get full answers. Asking the public to design an entire system goes beyond the point where you'll get useful, actionable responses.
There are plenty of examples on the web of how to download a file from a URL.
Suns version of the JDK and JRE includes the Mozilla Rhino scripting engine.
Assuming you have stored the contents of the javascript file in a string called 'script', you can execute scripts as follows
String result = null;
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
try {
jsEngine.eval(script);
result = jsEngine.get("result")
} catch (ScriptException ex) {
ex.printStackTrace();
}
The result will be extracted from the engine and stored in the 'result' variable.
The is a tutorial on scripting in Java that might be useful.