Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Request] Android ByteCode generation support #211

Open
F43nd1r opened this issue Jun 29, 2015 · 19 comments
Open

[Request] Android ByteCode generation support #211

F43nd1r opened this issue Jun 29, 2015 · 19 comments
Labels
Android Issues related to running Rhino on Android compilation docs Issues containing stuff that ought to be documented feature Issues considered a new feature

Comments

@F43nd1r
Copy link

F43nd1r commented Jun 29, 2015

Rhino works fine on Android with one big drawback: JavaAdapter can't be used, because it relies on Java bytecode, while android runs Dalvik bytecode.
Has anyone ever tried to create a version which removes this drawback in any way?
If not, can somebody do this or point me in a direction where I could start with this?

@eshepelyuk
Copy link
Contributor

Maybe you could try to use optimization level -1, so Rhino will not try to generate any bytecode ?
It will probably decrease performance, but maybe in your case it will not be a stopper.

@F43nd1r
Copy link
Author

F43nd1r commented Jun 29, 2015

Rhino does only work on android with optimization level set to -1, so this is already set.

here is the logcat of a simple test script for JavaAdapter:

java.lang.UnsupportedOperationException: can't load this type of class file
at java.lang.ClassLoader.defineClass(ClassLoader.java:288)
at org.mozilla.javascript.v.a(DefiningClassLoader.java:27)
at org.mozilla.javascript.JavaAdapter.a(JavaAdapter.java:333)
at org.mozilla.javascript.JavaAdapter.a(JavaAdapter.java:173)
at org.mozilla.javascript.JavaAdapter.execIdCall(JavaAdapter.java:86)
at org.mozilla.javascript.ah.a(IdFunctionObject.java:97)
at org.mozilla.javascript.b.a(BaseFunction.java:343)
at org.mozilla.javascript.ao.a(Interpreter.java:1519)
at org.mozilla.javascript.ao.a(Interpreter.java:815)
at org.mozilla.javascript.an.a(InterpretedFunction.java:109)
at org.mozilla.javascript.o.a(ContextFactory.java:394)
at org.mozilla.javascript.dn.a(ScriptRuntime.java:3091)
at org.mozilla.javascript.l.a(Context.java:1172)
at org.mozilla.javascript.l.a(Context.java:1139)
at net.pierrox.lightning_launcher.c.b.a(ScriptExecutor.java:498)
at net.pierrox.lightning_launcher.activities.ar.run(Dashboard.java:1702)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5086)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)

@gbrail
Copy link
Collaborator

gbrail commented Jun 29, 2015

Yes -- Rhino generates "regular" Java bytecode, so yes, if you want to be
in Dalvik or Art, that'll be the wrong kind of byte code. Generating a
different kind of bytecode would require someone to write a new back end
for Rhino (and since it only has one back end, there would be some
refactoring required to make that happen).

On Mon, Jun 29, 2015 at 11:53 AM, F43nd1r [email protected] wrote:

Rhino does only work on android with optimization level set to -1, so this
is already set.

here is the logcat of a simple test script for JavaAdapter:

java.lang.UnsupportedOperationException: can't load this type of class file
at java.lang.ClassLoader.defineClass(ClassLoader.java:288)
at org.mozilla.javascript.v.a(DefiningClassLoader.java:27)
at org.mozilla.javascript.JavaAdapter.a(JavaAdapter.java:333)
at org.mozilla.javascript.JavaAdapter.a(JavaAdapter.java:173)
at org.mozilla.javascript.JavaAdapter.execIdCall(JavaAdapter.java:86)
at org.mozilla.javascript.ah.a(IdFunctionObject.java:97)
at org.mozilla.javascript.b.a(BaseFunction.java:343)
at org.mozilla.javascript.ao.a(Interpreter.java:1519)
at org.mozilla.javascript.ao.a(Interpreter.java:815)
at org.mozilla.javascript.an.a(InterpretedFunction.java:109)
at org.mozilla.javascript.o.a(ContextFactory.java:394)
at org.mozilla.javascript.dn.a(ScriptRuntime.java:3091)
at org.mozilla.javascript.l.a(Context.java:1172)
at org.mozilla.javascript.l.a(Context.java:1139)
at net.pierrox.lightning_launcher.c.b.a(ScriptExecutor.java:498)
at net.pierrox.lightning_launcher.activities.ar.run(Dashboard.java:1702)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5086)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)


Reply to this email directly or view it on GitHub
#211 (comment).

Greg Brail | apigee https://apigee.com/ | twitter @gbrail
http://twitter.com/gbrail @apigee https://twitter.com/apigee
http://iloveapis.com/

@F43nd1r
Copy link
Author

F43nd1r commented Jun 30, 2015

I am just wondering why everything else - even implementing interfaces - works, but the JavaAdapter doesn't....

@gbrail
Copy link
Collaborator

gbrail commented Jul 1, 2015

The JavaAdapter also generates bytecode to do its job. It uses the same ClassFileWriter as the regular code generation, so that generates bytecode that's compatible with Java and apparently not with Dalvik. So depending on how different the bytecodes are, we'd have to create a new ClassFileWriter for different VMs.

@F43nd1r
Copy link
Author

F43nd1r commented Jan 8, 2016

I found a very interesting project: Dexmaker (https://github.com/crittercism/dexmaker). I tried to replace the current classfilewriter with a wrapper around the dexmaker. My problem is now: dexmakers methods operate on a higher level than those of classfilewriter. For example i can't implement add(int theOpCode), because dexmaker always expects some kind of target (e.g. a local variable). Is there a better point to plug this in? Or is it just plain stupid to try it because it won't fit? Any other comments?

@F43nd1r
Copy link
Author

F43nd1r commented Jan 14, 2016

OK, so I got my own project working on android with optimization in use by provididng custom class loading. For anyone who is interested - https://github.com/F43nd1r/rhino-android. It seems to work pretty good, altough I haven't tested it a lot.

@F43nd1r F43nd1r closed this as completed Jan 14, 2016
@gbrail
Copy link
Collaborator

gbrail commented Jan 15, 2016

Glad to hear it!

We've had a number of questions about running on Android, so if you ever
get your stuff into shape that it could be shared, you might want to
consider contributing a sample that we could put in the Rhino GitHub repo
so that others can easily find it.

On Thu, Jan 14, 2016 at 1:16 PM, F43nd1r [email protected] wrote:

Closed #211 #211.


Reply to this email directly or view it on GitHub
#211 (comment).

Greg Brail | apigee https://apigee.com/ | twitter @gbrail
http://twitter.com/gbrail @apigee https://twitter.com/apigee

@F43nd1r
Copy link
Author

F43nd1r commented Feb 12, 2016

I am currently working on running all the java tests on an android device. While most run fine, I don't understand some of the errors:

  • OverloadTest.testJSObjectToMap throws "org.mozilla.javascript.EvaluatorException: The choice of Java method org.mozilla.javascript.tests.OverloadTest.x matching JavaScript argument types (object) is ambiguous; candidate methods are:
    class java.lang.String x(java.util.Map)
    class java.lang.String x(java.util.Collection)
    class java.lang.String x(java.lang.Runnable)"
  • ParserTest.testReportError throws "junit.framework.ComparisonFailure: expected:<"[eval]" is not a valid ide...> but was:<"[{0}]" is not a valid ide...>"
  • ObjectToStringNullUndefinedTest.testToStringNullUndefined throws "org.junit.ComparisonFailure: expected:<[object [Null]]> but was:<[object [Object]]>"
  • ToSourceTest.testArrowFunctionToSource throws "org.mozilla.javascript.EvaluatorException: syntax error"
  • ErrorPropertiesTest.defaultStack throws "org.junit.ComparisonFailure: expected:< at myScript.js:3
    at myScript.js...> but was:< at myScript.js:2"
  • ErrorPropertiesTest.mozillaStack throws "org.junit.ComparisonFailure: expected:<f()@myScript.js:[3]
    @myScript.js:5
    .> but was:<f()@myScript.js:[2]
    @myScript.js:5"
  • ErrorPropertiesTest.lineNumber throws "java.lang.AssertionError: expected:<2> but was:<1>"
  • GeneratedMethodNameTest.testAnonymousFunction throws "org.mozilla.javascript.JavaScriptException: got callName0 (myScript#3)"
  • Bug419940Test.testAdapter fails if run together with Bug409702Test.testAdapter, because both create a class named adapter1, which makes the one executed second fail.
  • GeneratedMethodNameTest.testConstructor throws "org.mozilla.javascript.JavaScriptException: got construct (myScript#3)"
  • Other tests in GeneratedMethodNameTest throw similar errors

What do those mean?

  • The second one to be run of Bug409702Test and Bug419940Test fails, because both create a class named "adapter1"

How can this be resolved?

@F43nd1r
Copy link
Author

F43nd1r commented Feb 13, 2016

FYI here is a sample application showcasing how to use rhino on android, as you asked for.

@F43nd1r
Copy link
Author

F43nd1r commented Mar 12, 2016

reopen for awareness.

@F43nd1r F43nd1r reopened this Mar 12, 2016
@krudos
Copy link

krudos commented May 21, 2016

i am having problem with android kitkat and big js files around 500kb

@Betalord
Copy link

Hi,
I'd like to know what is the state of the matter currently? Has this problem been resolved? I'd need to use Rhino on Android with JavaAdapter (due to subclassing etc.), so I'm trying to figure out what my options are.

@F43nd1r
Copy link
Author

F43nd1r commented Aug 16, 2017

My project is running, altough according to some bug reports, it has problems in certain situations. The solution is not optimal, because it adds another compile step (someone with enough knowledge of both jvm and art bytecode could probably cut one compile step). Feel free to try the project - https://github.com/F43nd1r/rhino-android

@AlexTrotsenko
Copy link

AlexTrotsenko commented Jan 9, 2018

As I already mentioned in #282 (comment), Byte Buddy supports both Java and Android byte code generation - thus it could be a good option for Rhino as well.

@hypersoft
Copy link

hypersoft commented May 20, 2019

@F43nd1r , I managed to in-build your project with a custom rhino, that not only does the runtime compile classloading, it also changed the classloader profile to aggressive. Normally, if you request a package from the Mozilla Packages object, it caches the request, if the first request is a 404, adding to the classpath won't help. I built a URL classloader and injected it into the ContextFactory class as the default class loader for makeContext (single-instance). The classloader also keeps track of all package requests, so i can know what packages and classes have been loaded by the script runtime, (maybe even put a security or debug wrapper in there). My url classloader is not (directly) designed to be used by your ContextFactory (means: foreign+code+compatible:interface-synchronization-hard-limit).

Your method works fine with that, as far as I know. Good work by the way. I've managed to cut all the dalvik code, plus your project down to ~28KB.

Your code is AUTO injected into the mozilla Context at line 474 using a custom system detection routine i built.

https://github.com/hypersoft/NanoStarbox

@hypersoft
Copy link

hypersoft commented May 20, 2019

@mozilla, seems you could make it easy for android users to use your code, if you put the instrumentation to use his ContextFactory, when available in the Context as done here at line 474. Then an archive such as the nano-archive i have built, could automagically load for the android users with the simple addition of some class files to their own classpath.

Ideally, you would make that an api, for seamless context factory integration, perhaps using

Class nativeContextFactoryClass = null;
try { nativeContextFactoryClass = Class.forName(System.getProperty(MOZ_RHINO_PLATFORM_CONTEXT_FACTORY)); } 
catch(Exception ignored) {}
if (nativeContextFactoryClass != null) ... awesome stuff ...

@hypersoft
Copy link

hypersoft commented May 20, 2019

@F43nd1r , one more thing [okay two more], that nano archive, basically traces the Dalvik API route of your project. you can use that route, plus the sources to construct your own android debugging layer... The route in place is factory code.

It would also be nice if your project used the System.getProperty trick to setup the cache loader since you can't touch the android context which provides that api, from outside of the android api. This is crucial because each android-application has its own cache directory, and any autoloading would need a correct cache directory, for Certifiable Android Platform Integration [and make sure you wipe the property after loading, telling the user this will happen for security].

@hypersoft
Copy link

This is also very useful information for anyone Implementing an ART Just-In-Time (JIT) Compiler, such as Faendir's project. It details how to configure the platform for debugging and other tricks of the trade.

@p-bakker p-bakker added the Android Issues related to running Rhino on Android label Jun 29, 2021
@p-bakker p-bakker changed the title [Request] Android support [Request] Android ByteCode generation support Jul 5, 2021
@p-bakker p-bakker added feature Issues considered a new feature docs Issues containing stuff that ought to be documented labels Jul 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Android Issues related to running Rhino on Android compilation docs Issues containing stuff that ought to be documented feature Issues considered a new feature
Projects
None yet
Development

No branches or pull requests

8 participants