Problems using Rhino on Android
Asked Answered
H

3

18

I'm trying to use Mozilla Rhino in my Java application for Android to evaluate some JavaScript. I am using Eclipse + ADT plugin.

First I tried simply downloading the Rhino .jar file from Mozilla's website and adding it to the project as a library in Eclipse. Eclipse recognised it fine and compiled the application. However, when running it I get an exception when calling Context.evaluateReader() (see below for stack trace).

Then I tried adding the Rhino source code as a separate Android project in Eclipse, marking it as a library and referencing it in my project, which was enough to get Eclipse to get it to compile, but led to the same error.

This is the stacktrace I get (java.lang.UnsupportedOperationException: can't load this type of class file)

Thread [<7> Thread-8] (Suspended (exception UnsupportedOperationException)) 
    DefiningClassLoader(ClassLoader).defineClass(String, byte[], int, int, ProtectionDomain) line: 338  
    DefiningClassLoader.defineClass(String, byte[]) line: 62    
    Codegen.defineClass(Object, Object) line: 159   
    Codegen.createScriptObject(Object, Object) line: 114    
    Context.compileImpl(Scriptable, Reader, String, String, int, Object, boolean, Evaluator, ErrorReporter) line: 2440  
    Context.compileReader(Reader, String, int, Object) line: 1326   
    Context.compileReader(Scriptable, Reader, String, int, Object) line: 1298   
    Context.evaluateReader(Scriptable, Reader, String, int, Object) line: 1137  
    TimetableProcessor.evaluate(InputStream, String, String[]) line: 31 
    TimetableProcessor.processBasicData(InputStream, String) line: 58   
    TimetableProcessor.process(InputStream, String) line: 52    
    TimetableUpdater.update() line: 53  
    Main$1$1.run() line: 22

The bit of my code that hits the exception looks like this:

        Context cx = Context.enter();
        cx.setLanguageVersion(Context.VERSION_1_7);
        Scriptable scope = cx.initStandardObjects();
        try {
            Object result = cx.evaluateReader(scope, new InputStreamReader(data), /* <<< exception here */
                    filename, 0, null);
        } catch (IOException e) {
            // ...
        }

I also found this blog post which contains similar code and says it works. The author says he used a jar file from the Android Scripting site. The only jar file I found there was in rhino_extras_r3.zip. However, it doesn't contain .class files but rather a classes.dex file. When I added this as a library in Eclipse, it didn't recognise the classes it contains and thus failed to compile my project because of the missing references to Rhino classes.

Any help at all on how to get this to work is appreciated!

Hypnotherapy answered 4/10, 2010 at 21:33 Comment(0)
H
34

I finally got it to work. I should have paid more close attention to that blog post I linked.

If I add the line

cx.setOptimizationLevel(-1);

to disable optimisations, everything works perfectly.

Hypnotherapy answered 4/10, 2010 at 22:2 Comment(4)
By default, Rhino tries to generate JVM bytecode on the fly, as a sort of Javascript JIT. That's cool and all, but Android does not run JVM bytecode -- it runs Dalvik bytecode. Hence, you have to disable optimization, via the code snippet you showed, to allow Rhino to run.Neocene
You can use V8 instead of rhinoBurleson
How did you include the library?Spectrochemistry
Makes sense. Dalvik cannot directly take Java bytecode when a class is added on the fly. Is there a RhinoScriptEngine that is JSR 223-compliant and is non-GPL?Belak
N
11

An Android-compatible edition of rhino1_7R2.jar is available on the SL4A site, in the version control system. Here is a sample project that wraps up Rhino and BeanShell into an Android interpreter service.

Neocene answered 4/10, 2010 at 21:42 Comment(2)
Thanks, I didn't notice that jar file because it wasn't listed in the downloads section. It still didn't solve my problem (I've posted my actual solution), but you definitely deserve an upvote for showing me where the jar file is and the sample project that I can use as an example.Hypnotherapy
Here is the direct link: code.google.com/p/android-scripting/source/browse/rhino/…Ecclesiology
F
2

I've written a library which allows to run Rhino on Android.

Advantages include:

  • Rhino can only run on optimization level -1. The library supports all levels.
  • The library supports the use of JavaAdapter, which is not possible with base Rhino.
  • Altough i did not benchmark this, it should give a performance increase. (Compiled code is faster than interpreted code)

https://github.com/F43nd1r/rhino-android

Fairleigh answered 20/3, 2016 at 18:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.