ericwlange/AndroidJSCore

Running a 20k lines JS file make app no response

LiuHongtao opened this issue · 5 comments

I ran a 20k lines JS file like below. It made the app no response, or sometimes the first run is well.

var string;
var x;
var mycars = new Array();
mycars = new Array();
mycars[0] = "Saab";
mycars[1] = "Volvo";
mycars[2] = "BMW";

mycars = new Array();
mycars[0] = "Saab";
mycars[1] = "Volvo";
mycars[2] = "BMW";

mycars = new Array();
mycars[0] = "Saab";
mycars[1] = "Volvo";
mycars[2] = "BMW";

...

Activity code:

JSContext context;
long time =  0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    context = new JSContext();
}

public void toRunJS(View view) {
    String js = getFromAssets("test.js");
    context.evaluateScript(js);
    context.garbageCollect();
}

and Layout code:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.lht.jscoredemo.MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="RunJs"
        android:onClick="toRunJS"/>
</RelativeLayout>

Actually I want to run a 30k lines JS library and it's more complex than this, so I beg for your help.

Hi. Don't run JS in the UI thread. It will cause problems. Run it
asynchronously. Try this:

public void toRunJS(View view) {

final String js = getFromAssets("test.js");

new Thread() {

    @Override public run() {

        context.evaluateScript(js);

        context.garbageCollect(); // <-- not really necessary

    }

}).start();

}

On Tue, Sep 13, 2016 at 9:53 AM, 刘宏韬 notifications@github.com wrote:

I ran a 20k lines JS file like below. It made the app no response, or
sometimes the first run is well.

var string;
var x;
var mycars = new Array();
mycars = new Array();
mycars[0] = "Saab";
mycars[1] = "Volvo";
mycars[2] = "BMW";

mycars = new Array();
mycars[0] = "Saab";
mycars[1] = "Volvo";
mycars[2] = "BMW";

mycars = new Array();
mycars[0] = "Saab";
mycars[1] = "Volvo";
mycars[2] = "BMW";

...

Activity code:

JSContext context;
long time = 0;

@OverRide
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

context = new JSContext();

}

public void toRunJS(View view) {
String js = getFromAssets("test.js");
context.evaluateScript(js);
context.garbageCollect();
}

and Layout code:

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="RunJs"
    android:onClick="toRunJS"/>

Actually I want to run a 30k lines JS library and it's more complex than
this, so I beg for your help.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#40, or mute the
thread
https://github.com/notifications/unsubscribe-auth/ABIuZCmnXdnrQe13XyfOETLRM3JxZ3rBks5qpiVCgaJpZM4J7R2w
.

I rewrite the code and move JS code to a new thread. But problem still exists.

There is the new code:

public class MainActivity extends AppCompatActivity {

    static JSContext jsContext;
    String js;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        jsContext = new JSContext();
        jsContext.property("log", new JSFunction(jsContext, "log") {
            public void log(String msg) {
                Log.d("MainActivityLog", msg);
            }
        });
        jsContext.property("screenWidth", 768);
        jsContext.property("screenHeight", 1038);

        js = getFromAssets("test.js");
        thread.start();
    }

    Thread thread = new Thread() {
        @Override
        public void run() {
            super.run();

            jsContext.evaluateScript(js);
        }
    };

    public void toRunJS(View view) {
        Intent intent = new Intent();
        intent.setClass(this, Main2Activity.class);
        startActivity(intent);
    }
}

public class Main2Activity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        JSObject object = new JSObject(MainActivity.jsContext);
    }
}

The test.js is a 15k lines JS. When button clicked, code dead here:

JSObject object = new JSObject(MainActivity.jsContext);

public JSObject(JSContext ctx) {
→    context = ctx;
    ...
}

But if i remove one of three properties, it goes well:

        jsContext.property("log", new JSFunction(jsContext, "log") {
            public void log(String msg) {
                Log.d("MainActivityLog", msg);
            }
        });
        jsContext.property("screenHeight", 1038);

It always hangs in the same place? That is a surprising place for it to die. It is difficult for me to debug without a failing test case that I can reproduce. Can you provide the js? You can run it through uglify or whatever. I don't actually need to see it. The JS code is not the problem. I just need something which reproduces the issue reliably.

I'll send you an email with the test project.

Hi, I just commented on the issue "Multithreading and deadlock" and I wondered if this ticket was actually the same problem - Is it possible that the thing hanging this project is not the size of the evaluated JS, but instead the amount of data being passed into the "log" JSFunction via the JS <--> Java interface?

As a data-point, we can correctly evaluate a 350Kb JS file with no issues.