groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alain Stalder <astal...@span.ch>
Subject Re: Grape and loading classes that extend java.lang.Exception from compiled Groovy bytecode
Date Mon, 27 Feb 2017 12:06:21 GMT
PS: Below is what I get when I look at the Demo.class with the "JD" 
decompiler...

Is this maybe some kind of Grape concurrency issue similar to GROOVY-7407?

   https://issues.apache.org/jira/browse/GROOVY-7407

(I still get the same result when I am applying the workaround listed 
there - which I wrote myself, by the way - but maybe the workaround does 
not cover all possibilities?)


import groovy.grape.Grape;
import groovy.lang.Binding;
import groovy.lang.Script;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;

public class Demo extends Script
{
   public Demo()
   {
     Demo this;
     CallSite[] arrayOfCallSite = $getCallSiteArray();
   }

   public Demo(Binding context)
   {
     super(context);
   }

   public static void main(String[] args)
   {
     CallSite[] arrayOfCallSite = $getCallSiteArray();
     arrayOfCallSite[0].call(InvokerHelper.class, Demo.class, args);
   }

   public Object run()
   {
     CallSite[] arrayOfCallSite = $getCallSiteArray();
     try { try { 
arrayOfCallSite[1].call(arrayOfCallSite[2].callConstructor(SimpleEmail.class));
       } catch (EmailException e)
       {
         return Boolean.valueOf(true);
       } } finally {  }

     return Boolean.valueOf(false); return null;
   }

   static
   {
     $getCallSiteArray()[3].callStatic(Grape.class, 
ScriptBytecodeAdapter.createMap(new Object[0]), 
ScriptBytecodeAdapter.createMap(new Object[] { "group", 
"org.apache.commons", "module", "commons-email", "version", "1.3.3" }));
   }
}


On 27.02.17 10:51, Alain Stalder wrote:
> Maybe someone can point me in the right direction regarding the 
> following issue with Grape...
>
> Issue in code (in words further below):
>
> -- 
> import org.codehaus.groovy.control.CompilerConfiguration
>
> def demoScriptText = """\
> @Grab('org.apache.commons:commons-email:1.3.3')
> import org.apache.commons.mail.*
>
> try {
>   new SimpleEmail().send()
> } catch (EmailException e) {
>   // expected
>   return true
> }
> return false
> """
>
> // setup/clean target directory for script class
> File targetDir = new File('demo-target')
> if (!targetDir.exists()) {
>   assert targetDir.mkdir()
> }
> File classFile = new File(targetDir, 'Demo.class')
> if (classFile.exists()) {
>   assert classFile.delete()
> }
>
> // parse+run script with first GroovyClassLoader
> def config = new CompilerConfiguration()
> config.setTargetDirectory(targetDir)
> def loader1 = new 
> GroovyClassLoader(Thread.currentThread().contextClassLoader, config)
> def script1 = loader1.parseClass(demoScriptText, 
> 'Demo.groovy').newInstance()
> assert script1.run()
>
> // load compiled script class with second GroovyClassLoader
> def loader2 = new GroovyClassLoader()
> loader2.addClasspath(targetDir.path)
> try {
>   def script2 = loader2.loadClass('Demo').newInstance()
>   assert false
> } catch (NoClassDefFoundError e) {
>   println 'Failed as expected:'
>   println()
>   println e
>   println()
>   println e.stackTrace
> }
> -- 
>
> Issue in words:
>
> - Compile a script that uses Grape to load a dependency and use a class
>   that extends java.lang.Exception from that dependency in the script.
> - Loading and running that script with the GroovyClassLoader that 
> compiled
>   it, works fine.
> - Then try to load the class from its class file (bytecode) with a new
>    GroovyClassLoader; this fails with a NoClassDefFoundError.
> - (Apparently has nothing specifically to do with commons-email, same 
> effect
>   with Commons httpclient and an Exception class declared there.)
>
> The strange thing about this is that in the example above, 
> EmailException is
> not found, but SimpleEmail - which is in the same grabbed JAR - is found!
> In fact, if I change the catch in the script to "catch (Exception e)", 
> I can
> load and run the script from its class file without any problems.
>
> Question:
>
> Any ideas what could cause this, or where to look closer or maybe how to
> circumvent this by compiling the class differently?
>
> (My concrete use case is with Grengine, where I do not compile to a class
> in the file system, but to cached bytecode.)
>
> Alain
>
> -- 
>
> Here is the output I get (Groovy 2.4.8, JDK 1.8.0_121, Mac):
>
> Failed as expected:
>
> java.lang.NoClassDefFoundError: org/apache/commons/mail/EmailException
>
> [java.lang.Class.forName0(Native Method), 
> java.lang.Class.forName(Class.java:348), 
> org.codehaus.groovy.runtime.callsite.CallSiteArray$1.run(CallSiteArray.java:68), 
> org.codehaus.groovy.runtime.callsite.CallSiteArray$1.run(CallSiteArray.java:65), 
> java.security.AccessController.doPrivileged(Native Method), 
> org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallStaticSite(CallSiteArray.java:65),

> org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallSite(CallSiteArray.java:162),

> org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48),

> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113),

> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117),

> demo.run(demo.groovy:37), 
> groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:263), 
> groovy.lang.GroovyShell.run(GroovyShell.java:518), 
> groovy.lang.GroovyShell.run(GroovyShell.java:497), 
> groovy.lang.GroovyShell.run(GroovyShell.java:170), 
> groovy.lang.GroovyShell$run$1.call(Unknown Source), 
> groovy.ui.Console$_runScriptImpl_closure16.doCall(Console.groovy:1005), 
> groovy.ui.Console$_runScriptImpl_closure16.doCall(Console.groovy), 
> sun.reflect.GeneratedMethodAccessor296.invoke(Unknown Source), 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43),

> java.lang.reflect.Method.invoke(Method.java:498), 
> org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93), 
> groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325), 
> org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294),

> groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1027), 
> groovy.lang.Closure.call(Closure.java:414), 
> groovy.lang.Closure.call(Closure.java:408), 
> groovy.lang.Closure.run(Closure.java:495), 
> java.lang.Thread.run(Thread.java:745)]
>
> .
>


Mime
View raw message