Skip to content

Stackoverflow with NativeJSON.stringify after update from 1.7.7 to 1.7.11 #578

@heywiki

Description

@heywiki

NativeJSON.stringify used to throw an exception when it experienced a problem. This way it was possible to identify the problem in the json string, usually an object that was a java string. Now (since 1.7.8) it goes into a Stackoverflow. This should be changed imho. To see how i struggeld to find out what was going on i left my analysis below.

We upgraded from 1.7.7 to version 1.7.11. After that update we now get a Stackoverflow for the following code that finally uses org.mozilla.javascript.NativeJSON.stringify() on the Java side. It seems that this occurs if you add a Java object to the json you want to stringify. The following example uses trim to generate a java string, you could however also use another object like Joda DateTime etc to provoke the stackoverflow.

Here's the client code

var Util =
{
    getModel : function(x)
    {
        var model = {
            x : x,
        }
        return model;
    },
}

//example for a java object in the json:
var x = new Packages.java.lang.String("Hello World").trim(); //-> Stackoverfow 
//var x = "Hello World"; -> works fine
var model = Util.getModel(x);

println(new Packages.org.acme.commons.lang.RhinoUtil.jsonStringify(model));

And here's the code for the RhinoUtil.jsonStringify()

    public static final String jsonStringify(NativeObject nativeObj)
    {
        ContextFactory cf = null;
        try
        {
            cf = new ContextFactory();
        }
        catch (NoClassDefFoundError nce)
        {
            throw nce;
        }

        Context cx = cf.enterContext();
        try 
        {   
            ScriptableObject sealedSharedScope = cx.initStandardObjects(null, true); //sealed object
            String loadMe = "RegExp; getClass; java; Packages; JavaAdapter;";
            cx.evaluateString(sealedSharedScope , loadMe, "lazyLoad", 0, null);
            sealedSharedScope.sealObject();

            return NativeJSON.stringify(cx, sealedSharedScope, nativeObj, null, null) + "";
        }
        finally
        {
            Context.exit();
        }
    }

If we analyse the stackoverflow exception we get the following stacktrace

java.lang.StackOverflowError
at org.mozilla.javascript.JavaMembers.getIds(JavaMembers.java:177)
at org.mozilla.javascript.NativeJavaObject.getIds(NativeJavaObject.java:188)
at org.mozilla.javascript.NativeJSON.jo(NativeJSON.java:353)
at org.mozilla.javascript.NativeJSON.str(NativeJSON.java:322)
at org.mozilla.javascript.NativeJSON.jo(NativeJSON.java:359)
at org.mozilla.javascript.NativeJSON.str(NativeJSON.java:322)
at org.mozilla.javascript.NativeJSON.jo(NativeJSON.java:359)
at org.mozilla.javascript.NativeJSON.str(NativeJSON.java:322)
...

Please note that we need a way to stringify on the java side, therefore js JSON.stringify() is not an option. Please help.

Tested same code with 1.7.7 and it seems that it never worked, however the 1.7.7 error message was more clear

Java class "[Ljava.lang.reflect.Constructor;" has no public instance field or method named "toJSON"

Note that i also changed my jdk from oracle do adopt open jdk 1.8. Will research further...

Ok, found out that our internal util already checks for this and has a fallback

NativeObject nativeObj = (NativeObject) object;
try
{
	//this will fail if the json contains a Java String, therefore we will use a fallback
	return RhinoUtil.jsonStringify(nativeObj);
}
catch (Exception e)
{
        // fallback to old style iteration with nativeObject.getIds()
	return JSONStringifier.jsonStringify(nativeObj);
}

I now changed the catch from Exception to Throwable so that it also gets the Stackoverflow which is Throwable, not Exception. Now everything works as before. So actually for me the problme is solved and we can continue to use 1.7.11. Sorry for that elaborate story. But it shows that it would be useful to avoid the Stackoverflow and change it to the previous exception that was easier to understand.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIssues considered a bug

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions