GroovySunClassLoader and SunClassLoader appear to be broken

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

GroovySunClassLoader and SunClassLoader appear to be broken

harada.tomokazu.9p8@jp.nssol.nipponsteel.com
Dear All,

I noticed that GroovySunClassLoader and SunClassLoader are broken.

I tried to use a Groovy script in Java and noticed that GroovySunClassLoader.sunVM was null.
I'm using OpenJDK 8u252 and it has sun.reflect.MagicAccessorImpl, so GroovySunClassLoader.sunVM should not be null.

In my investigation the constructor argument for GroovySunClassLoader seems to be wrong:

    protected GroovySunClassLoader() throws Throwable {
        this(ClassReader.SKIP_CODE);  // <- should be ClassReader.SKIP_DEBUG or 0
    }


I applied the above fix to Groovy and ran the following test program, but the test failed.
-----------------------------
package app;

import groovy.lang.GroovyShell;
import org.codehaus.groovy.runtime.callsite.GroovySunClassLoader;

public class Main {
    public static void main(String[] args) {
        System.out.println("sunVM: " + GroovySunClassLoader.sunVM);
        GroovyShell shell = new GroovyShell();
        String name = (String) shell.evaluate("new app.Main().getName()");
        System.out.println(name);
    }

    private String getName() {
        return "abc";
    }
}
-----------------------------

The output of the test program:

sunVM: org.codehaus.groovy.runtime.callsite.GroovySunClassLoader@27bc2616
Exception in thread "main" java.lang.IllegalAccessError: tried to access method app.Main.getName()Ljava/lang/String; from class app.Main$getName
    at app.Main$getName.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130)
    at Script1.run(Script1.groovy:1)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:427)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:461)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:436)
    at app.Main.main(Main.java:11)


IllegalAccessError seems to occur as MagicAccessorImpl is not effective.
This is because SunClassLoader.define() does not define a class for the current class loader.
Classes are defined in GroovySunClassLoader but they are not used.

I think that GroovySunClassLoader and SunClassLoader should be disabled for a while.


Regards,
Tomokazu Harada
*****************************************************************
This e-mail and any attachments are intended only for
the named addressee(s) and may contain confidential information.
If you have received this e-mail in error, please delete
the e-mail and any attachments and notify the sender immediately.
If you are not the intended recipient, any disclosure, copying,
printing, transmission or distribution of, or any action taken
in reliance upon, the information contained in this e-mail and
any attachments is strictly prohibited.

このメール及び添付資料には機密情報を含む場合があります。
本メールにお心当たりのない場合は、速やかに破棄頂くとともに、
送信元へその旨ご連絡ください。また、本メール及び添付資料に
ついては、一切の開示、複写、配布、その他の利用、または、
記載内容に基づくいかなる行動もされないようにお願いします。
*****************************************************************
Reply | Threaded
Open this post in threaded view
|

Re: GroovySunClassLoader and SunClassLoader appear to be broken

Jochen Theodorou
On 29.05.20 03:39, [hidden email] wrote:
> Dear All,
>
> I noticed that GroovySunClassLoader and SunClassLoader are broken.
>
> I tried to use a Groovy script in Java and noticed that GroovySunClassLoader.sunVM was null.
> I'm using OpenJDK 8u252 and it has sun.reflect.MagicAccessorImpl, so GroovySunClassLoader.sunVM should not be null.
>
[...]

> I applied the above fix to Groovy and ran the following test program, but the test failed.
> -----------------------------
> package app;
>
> import groovy.lang.GroovyShell;
> import org.codehaus.groovy.runtime.callsite.GroovySunClassLoader;
>
> public class Main {
>      public static void main(String[] args) {
>          System.out.println("sunVM: " + GroovySunClassLoader.sunVM);
>          GroovyShell shell = new GroovyShell();
>          String name = (String) shell.evaluate("new app.Main().getName()");
>          System.out.println(name);
>      }
>
>      private String getName() {
>          return "abc";
>      }
> }
> -----------------------------

this means you want the Groovy program to access the private method a
Java class, right?

> The output of the test program:
>
> sunVM: org.codehaus.groovy.runtime.callsite.GroovySunClassLoader@27bc2616
> Exception in thread "main" java.lang.IllegalAccessError: tried to access method app.Main.getName()Ljava/lang/String; from class app.Main$getName
>      at app.Main$getName.call(Unknown Source)
>      at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
>      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
>      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130)
>      at Script1.run(Script1.groovy:1)
>      at groovy.lang.GroovyShell.evaluate(GroovyShell.java:427)
>      at groovy.lang.GroovyShell.evaluate(GroovyShell.java:461)
>      at groovy.lang.GroovyShell.evaluate(GroovyShell.java:436)
>      at app.Main.main(Main.java:11)
>
> IllegalAccessError seems to occur as MagicAccessorImpl is not effective.

Does MagicAccessorImpl prevent access checks? It does prevent bytecode
verification, which allows us to load the generated class faster.

But I don't think that this access check falls under the magic as well.
Groovy should have accessed by reflection only instead in non-indy mode.

Could you please tell us the version of Groovy you are using as well?

bye Jochen

Reply | Threaded
Open this post in threaded view
|

RE: GroovySunClassLoader and SunClassLoader appear to be broken

harada.tomokazu.9p8@jp.nssol.nipponsteel.com
Dear Jochen,

>this means you want the Groovy program to access the private method a
>Java class, right?

Yes, I intend that.

>Does MagicAccessorImpl prevent access checks? It does prevent bytecode
>verification, which allows us to load the generated class faster.

Yes, according to the javadoc of MagicAccessorImpl it prevents access checking and bytecode verification.

>But I don't think that this access check falls under the magic as well.
>Groovy should have accessed by reflection only instead in non-indy mode.

At first I thought so too, but it seems that Groovy calls the private method directly.
I think that some direct calling byte-code is generated by CallSiteGenerator.compilePojoMethod()
in CachedMethod.createPojoMetaMethodSite().

>Could you please tell us the version of Groovy you are using as well?

I'm using Groovy 3.0.3 with Windows 10.

Regards,
Tomokazu Harada
*****************************************************************
This e-mail and any attachments are intended only for
the named addressee(s) and may contain confidential information.
If you have received this e-mail in error, please delete
the e-mail and any attachments and notify the sender immediately.
If you are not the intended recipient, any disclosure, copying,
printing, transmission or distribution of, or any action taken
in reliance upon, the information contained in this e-mail and
any attachments is strictly prohibited.

このメール及び添付資料には機密情報を含む場合があります。
本メールにお心当たりのない場合は、速やかに破棄頂くとともに、
送信元へその旨ご連絡ください。また、本メール及び添付資料に
ついては、一切の開示、複写、配布、その他の利用、または、
記載内容に基づくいかなる行動もされないようにお願いします。
*****************************************************************