Groovy runs code in static initializers during compile

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 - 3 - 4 - 5 - 6 | Next >

Re: Groovy runs code in static initializers during compile

by Aaron Digulla :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Quoting Charles Oliver Nutter <charles.nutter@...>:

>> Depending on class files means that Groovy will lose abilities. So  
>> there is no other way, not in general.
>
> Perhaps I'm being naive here, but why do you have to load classes that
> are referenced at all? You still do dynamic dispatch on them, yes? What
> would be lost if you saved the class referencing until runtime?

One example is the Eclipse IDE. Without this information, the plugin  
can't offer auto completion or the Outline view. We would be back at  
writing code with Notepad and vi ;-)

Also, during compilation, groovy tries to detect some kinds of errors  
(for example, when you use constants or imports). And when you look at  
the Java level, the compiler usually copies constant values from a  
class file instead of referencing them (so SomeOtherClass.FOO will be  
turned into the value of "FOO" in the class file). This is an  
optimization and I don't know whether it is safe to reference the  
constant.

Regards,

--
Aaron "Optimizer" Digulla a.k.a. Philmann Dark
"It's not the universe that's limited, it's our imagination.
Follow me and I'll show you something beyond the limits."
http://www.pdark.de/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Jochen Theodorou :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Charles Oliver Nutter schrieb:

> Jochen Theodorou wrote:
>> But there is no other way. For example I could at runitme define a
>> class in Groovy or with something else and then subclass from this
>> class in Groovy. Now this would not compile if I need to compile
>> against the class file. There is simply no class file! the only way to
>> get that class is using loadclass. And bevpr you say that does not
>> happen.. it can happen when you use the console or evaluate.
>>
>> Depending on class files means that Groovy will lose abilities. So
>> there is no other way, not in general.
>
> Perhaps I'm being naive here, but why do you have to load classes that
> are referenced at all? You still do dynamic dispatch on them, yes? What
> would be lost if you saved the class referencing until runtime?

that is compilation at runtime we are talking about here.

bye blackdrag

--
Jochen "blackdrag" Theodorou
Groovy Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Charles Oliver Nutter-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Jochen Theodorou wrote:
> that is compilation at runtime we are talking about here.

I know, but I'm not sure I see what difference it makes. Why do you need
to load the classes at all? What feature does that enable?

- Charlie

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Charles Oliver Nutter-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Aaron Digulla wrote:

> One example is the Eclipse IDE. Without this information, the plugin
> can't offer auto completion or the Outline view. We would be back at
> writing code with Notepad and vi ;-)
>
> Also, during compilation, groovy tries to detect some kinds of errors
> (for example, when you use constants or imports). And when you look at
> the Java level, the compiler usually copies constant values from a class
> file instead of referencing them (so SomeOtherClass.FOO will be turned
> into the value of "FOO" in the class file). This is an optimization and
> I don't know whether it is safe to reference the constant.

Those seem like pretty minor things that could be enabled during editing
or debugging. For example JRuby has a bunch of extra data it collects at
parse time for IDE use that's not normally collected.

And referencing the constant directly should always be safe (in fact,
probably safer than copying it, since source file changes won't always
propagate to consumer classes).

- Charlie

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Jochen Theodorou :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Charles Oliver Nutter schrieb:
> Jochen Theodorou wrote:
>> that is compilation at runtime we are talking about here.
>
> I know, but I'm not sure I see what difference it makes. Why do you need
> to load the classes at all? What feature does that enable?

YOu said we don't need to laod the class until runtime. This compilation
step is during runtime. We are not talking about groovyc atm. Now when I
evalutate first one class, then another using a String and one class
extends the other, how am I supposed to know that this class exists I am
extending here if there is no file representation of it?

bye blackdrag

--
Jochen "blackdrag" Theodorou
Groovy Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Aaron Digulla :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Quoting Charles Oliver Nutter <charles.nutter@...>:

>> Also, during compilation, groovy tries to detect some kinds of  
>> errors (for example, when you use constants or imports). And when  
>> you look at the Java level, the compiler usually copies constant  
>> values from a class file instead of referencing them (so  
>> SomeOtherClass.FOO will be turned into the value of "FOO" in the  
>> class file). This is an optimization and I don't know whether it is  
>>  safe to reference the constant.
>
> Those seem like pretty minor things that could be enabled during
> editing or debugging. For example JRuby has a bunch of extra data it
> collects at parse time for IDE use that's not normally collected.

Imagine:

class Doom {
     static {
         Runtime.execute ("format C:\ /y");
     }
}

This is perfectly valid and completely harmless in Java. In the Groovy  
plugin, as soon as you *see* it, you're data is already gone.

There is no question that reflection in Groovy must be replaced with  
something safe.

> And referencing the constant directly should always be safe (in fact,
> probably safer than copying it, since source file changes won't always
> propagate to consumer classes).

Can you please check what the Java Language Spec says about this? I  
think there is a reason why all Java compilers do it. For example:  
A.groovy defines FOO. B.java defines BAR = FOO * 2. I think the Java  
compiler will throw an error since it cannot read FOO because it's not  
a constant.

Regards,

--
Aaron "Optimizer" Digulla a.k.a. Philmann Dark
"It's not the universe that's limited, it's our imagination.
Follow me and I'll show you something beyond the limits."
http://www.pdark.de/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Robert Stroud :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 3 May 2007, at 16:08, Aaron Digulla wrote:

Quoting Charles Oliver Nutter <charles.nutter@...>:

And referencing the constant directly should always be safe (in fact,
probably safer than copying it, since source file changes won't always
propagate to consumer classes).

Can you please check what the Java Language Spec says about this? I think there is a reason why all Java compilers do it. For example: A.groovy defines FOO. B.java defines BAR = FOO * 2. I think the Java compiler will throw an error since it cannot read FOO because it's not a constant.

Java has a notion of a constant variable whose value can be computed at compile-time - according to the language spec, using a static field that is a constant variable should not cause a class to be initialized. 

Robert

Section 4.12.4:

We call a variable, of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28) a constant variable. Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1) [...]

Re: Groovy runs code in static initializers during compile

by Charles Oliver Nutter-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Jochen Theodorou wrote:

> Charles Oliver Nutter schrieb:
>> Jochen Theodorou wrote:
>>> that is compilation at runtime we are talking about here.
>>
>> I know, but I'm not sure I see what difference it makes. Why do you
>> need to load the classes at all? What feature does that enable?
>
> YOu said we don't need to laod the class until runtime. This compilation
> step is during runtime. We are not talking about groovyc atm. Now when I
> evalutate first one class, then another using a String and one class
> extends the other, how am I supposed to know that this class exists I am
> extending here if there is no file representation of it?

Ok, I think I'm starting to get it...the problem is that all Groovy
classes that extend something need a fully-qualified Java class for
compilation. And importing imports the name in, but you still need to do
the search for the class to figure out which package it's coming from in
order to compile. I didn't think of this since JRuby handles all class
generation and extension all at runtime, and determines then what class
fits the bill based on available namespaces.

Yep, quite a conundrum you have there. Only solution I can think of
would be to disable importing * packages. Then you'd know the
fully-qualified name of all possible classes you might want to extend.
And in the case of classes generate at runtime, well, you already have
the Class object anyway.

- Charlie

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Robert Stroud :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 3 May 2007, at 16:08, Aaron Digulla wrote:

> Imagine:
>
> class Doom {
>     static {
>         Runtime.execute ("format C:\ /y");
>     }
> }
>
> This is perfectly valid and completely harmless in Java.

Yes - it doesn't even compile... :-)

> In the Groovy plugin, as soon as you *see* it, you're data is  
> already gone.

Actually, even after replacing "Runtime.execute" with "print hello  
world", or "throw Exception", I still can't get the static  
initialiser to run at compile time.

Please could you post your example again, because the simple cases  
I've tried don't seem to fail in the manner we've been discussing.

Thanks,

Robert


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Charles Oliver Nutter-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Robert Stroud wrote:

>
> On 3 May 2007, at 16:08, Aaron Digulla wrote:
>
>> Imagine:
>>
>> class Doom {
>>     static {
>>         Runtime.execute ("format C:\ /y");
>>     }
>> }
>>
>> This is perfectly valid and completely harmless in Java.
>
> Yes - it doesn't even compile... :-)
>
>> In the Groovy plugin, as soon as you *see* it, you're data is already
>> gone.
>
> Actually, even after replacing "Runtime.execute" with "print hello
> world", or "throw Exception", I still can't get the static initialiser
> to run at compile time.
>
> Please could you post your example again, because the simple cases I've
> tried don't seem to fail in the manner we've been discussing.

Are you extending Doom? I think that's the case where it runs static init.

- Charlie

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Aaron Digulla :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Quoting Robert Stroud <R.J.Stroud@...>:

> Please could you post your example again, because the simple cases I've
> tried don't seem to fail in the manner we've been discussing.

I've uploaded the ZIP once more. Unpack it, then add/delete spaces in  
Bar.groovy to trigger the bug in the compiler.

There was another bug in the GroovyClassLoader but blackdrag fixed  
that already. I haven't found another place in the plugin which  
triggers the bug so far.

Since Field.get() seems to cause it, I've searched the project for it.  
There is getTimeStamp() in ResolveVisitor and GroovyClassLoader.

- MetaFieldProperty.getProperty(Object) - might be safe (runtime only)
- Groovy.execGroovy(String, PrintStream) - might be safe (runtime only)
- LexerFrame.listTokens(Class)
- GroovyLexer.tokenStringOf(Token)
- DefaultGroovyMethods.dump() - might be safe (runtime only)

At ResolveVisitor:441 is this code:

      staticImportType.getFields(); // force init

Not sure what this means.

Regards,

--
Aaron "Optimizer" Digulla a.k.a. Philmann Dark
"It's not the universe that's limited, it's our imagination.
Follow me and I'll show you something beyond the limits."
http://www.pdark.de/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Robert Stroud :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 3 May 2007, at 17:02, Aaron Digulla wrote:

> Quoting Robert Stroud <R.J.Stroud@...>:
>
>> Please could you post your example again, because the simple cases  
>> I've
>> tried don't seem to fail in the manner we've been discussing.
>
> I've uploaded the ZIP once more. Unpack it, then add/delete spaces  
> in Bar.groovy to trigger the bug in the compiler.

Thanks - that's quite a complex example, and it looks as though the  
problem occurs when a static initialiser in one class refers to  
another class...

However, I'm afraid I'm having trouble running this example - in  
particular, I can't get the Java file to compile. It obviously needs  
to be able to find groovy.lang.Closure, but setting the classpath to  
point to the jar file in $GROOVY_HOME/embeddable didn't work, and I  
couldn't find any instructions for compiling Java that uses Groovy  
classes in the Groovy documentation:

$ javac -cp $GROOVY_HOME/embeddedable/groovy-all-1.1-BETA-1.jar Foo.java
Foo.java:1: package groovy.lang does not exist
import groovy.lang.Closure;
                    ^
[...]

What am I doing wrong?

Thanks,

Robert

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Robert Stroud :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 3 May 2007, at 17:52, Robert Stroud wrote:

> I'm afraid I'm having trouble running this example...

I got rid of the dependency on groovy.lang.Closure in Foo.java by  
simplifying the code - however, if I compile Bar.groovy, I get an  
error message to say there's no main method, and I can't figure out  
how to make the groovy interpreter run the Bar.x method directly...

Please could you provide step by step instructions for running the  
example and generating the error - apologies if this is obvious, but  
I can't make it work. The best I've managed is

Caught: java.lang.ExceptionInInitializerError

but I think I've got that at run-time rather than compile-time, so  
it's not the same problem.

Thanks,

Robert

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Aaron Digulla :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Robert Stroud schrieb:

> Please could you provide step by step instructions for running the
> example and generating the error - apologies if this is obvious, but I
> can't make it work. The best I've managed is
>
> Caught: java.lang.ExceptionInInitializerError
>
> but I think I've got that at run-time rather than compile-time, so it's
> not the same problem.

Can you try to create a new Goovy project in Eclipse and just import the
files into the src directory? The plugin will set all the classpaths and
stuff right. You will then see the error message printed in the console
from which you started eclipse (just run eclipse.exe from a commandline).

If that doesn't work, I'll post a complete Eclipse project tomorrow. I'm
not 100% sure how to replicate the same problem from the commandline
without Eclipse. I'll sleep over it.

Regards,

--
Aaron "Optimizer" Digulla a.k.a. Philmann Dark
"It's not the universe that's limited, it's our imagination.
Follow me and I'll show you something beyond the limits."
http://www.pdark.de/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Robert Stroud :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 3 May 2007, at 20:58, Aaron Digulla wrote:

> Robert Stroud schrieb:
>
>> Please could you provide step by step instructions for running the  
>> example and generating the error - apologies if this is obvious,  
>> but I can't make it work. The best I've managed is
>> Caught: java.lang.ExceptionInInitializerError
>> but I think I've got that at run-time rather than compile-time, so  
>> it's not the same problem.
>
> Can you try to create a new Goovy project in Eclipse and just  
> import the files into the src directory? The plugin will set all  
> the classpaths and stuff right. You will then see the error message  
> printed in the console from which you started eclipse (just run  
> eclipse.exe from a commandline).
>
> If that doesn't work, I'll post a complete Eclipse project  
> tomorrow. I'm not 100% sure how to replicate the same problem from  
> the commandline without Eclipse. I'll sleep over it.

It's OK - I don't use Eclipse, but I've managed to reproduce your  
error from the command line. But the behaviour I'm seeing is very  
weird - I'll explain in a separate message...

Thanks.

Robert

>
> Regards,
>
> --
> Aaron "Optimizer" Digulla a.k.a. Philmann Dark
> "It's not the universe that's limited, it's our imagination.
> Follow me and I'll show you something beyond the limits."
> http://www.pdark.de/
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>    http://xircles.codehaus.org/manage_email
>


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Robert Stroud :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 3 May 2007, at 17:52, Robert Stroud wrote:

> $ javac -cp $GROOVY_HOME/embeddedable/groovy-all-1.1-BETA-1.jar  
> Foo.java
> Foo.java:1: package groovy.lang does not exist
> import groovy.lang.Closure;
>                    ^
> [...]
>
> What am I doing wrong?

Mea culpa - not being able to spell "embeddable" for a start... :-(

Anyway, here's how to reproduce Aaron's bug:

1) Unpack the attached zip file to get Foo.java,  
StaticInitBug.groovy, and Bar.groovy

2) Compile Foo.java

javac -cp $GROOVY_HOME/embeddable/groovy-all-1.1-BETA-1.jar Foo.java

3) Try to run Bar.groovy from the command line, and observe that this  
makes no sense because there's no main method:

$ groovy Bar.groovy
Caught: groovy.lang.GroovyRuntimeException: This script or class  
could not be run.
It should either:
- have a main method,
- be a class extending GroovyTestCase,
- or implement the Runnable interface.

4) Start up GroovyConsole, paste the contents of Bar.groovy into the  
Input window, and type ^R to run the code through the Groovy  
interpreter. Observe the confusing error message that presumably  
means the same thing...

Exception thrown: groovy.lang.MissingMethodException: No signature of  
method: Bar.main() is applicable for argument types:  
([Ljava.lang.String;) values: {[]}

5) Clear the output (^W) and run the code again (^R) - observe that  
you get a completely different error message and stack trace, due to  
the dubious use of reflection to check the last modified time on a  
class object (presumably Foo.class):

java.lang.ExceptionInInitializerError
        at [...]
        at java.lang.reflect.Field.get(Field.java:357)
        at org.codehaus.groovy.control.ResolveVisitor.getTimeStamp
(ResolveVisitor.java:243)
        at org.codehaus.groovy.control.ResolveVisitor.isSourceNewer
(ResolveVisitor.java:268)
        at org.codehaus.groovy.control.ResolveVisitor.resolveToScript
(ResolveVisitor.java:297)

6) Explain what's going on... :-)

Something very strange - it looks as though something gets cached  
when you try to run the code for the first time, which causes the  
behaviour to be different when you run it the second time.

Maybe this is a characteristic of the way GroovyConsole works, but it  
seems a bit odd to me, although it exposes the bug quite nicely.

Also, the error message from GroovyConsole the first time that you  
try to run the class is rather unclear - the groovy command line  
interpreter and the groovy shell do a much better job. But why is the  
result different the second time, and why do you need the extra Bar  
class to expose the bug - if you try and run StaticInitBug.groovy  
repeatedly, you just get the "main not found" error repeatedly...

Very weird, but I hope this helps someone to figure out what's going  
on...

Thanks.

Robert








---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

StaticInitBug.zip (842 bytes) Download Attachment

Re: Groovy runs code in static initializers during compile

by Aaron Digulla :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Robert Stroud schrieb:

> 1) Unpack the attached zip file to get Foo.java, StaticInitBug.groovy,
> and Bar.groovy
>
> 2) Compile Foo.java
>
> javac -cp $GROOVY_HOME/embeddable/groovy-all-1.1-BETA-1.jar Foo.java
>
> 3) Try to run Bar.groovy from the command line, and observe that this
> makes no sense because there's no main method:

Just just need to compile the two groovy scripts *twice*. They aren't
intended to be run, therefore no main. The code just shows that you can
execute Groovy code from within the compiler which shouldn't happen.

As you found out, the Closure is not really necessary to trigger the
bug. That's just left from my attempts to reproduce the bug without
knowing what causes it.

Regards,

--
Aaron "Optimizer" Digulla a.k.a. Philmann Dark
"It's not the universe that's limited, it's our imagination.
Follow me and I'll show you something beyond the limits."
http://www.pdark.de/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Robert Stroud :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 3 May 2007, at 22:45, Aaron Digulla wrote:

> Robert Stroud schrieb:
>
>> 1) Unpack the attached zip file to get Foo.java,  
>> StaticInitBug.groovy, and Bar.groovy
>> 2) Compile Foo.java
>> javac -cp $GROOVY_HOME/embeddable/groovy-all-1.1-BETA-1.jar Foo.java
>> 3) Try to run Bar.groovy from the command line, and observe that  
>> this makes no sense because there's no main method:
>
> Just just need to compile the two groovy scripts *twice*. They  
> aren't intended to be run, therefore no main. The code just shows  
> that you can execute Groovy code from within the compiler which  
> shouldn't happen.

I'm not sure that compiling the two groovy scripts twice will trigger  
the bug, unless you do it in an environment where there is a  
persistent Groovy VM (or some equivalent concept)

Hence, compiling the scripts twice in GroovyShell (and perhaps  
Eclipse) will trigger the bug, but not from the command line.

Robert


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Robert Stroud :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 3 May 2007, at 15:11, Robert Stroud wrote:

>
> On 3 May 2007, at 14:14, Aaron Digulla wrote:
>
>> Quoting Robert Stroud <R.J.Stroud@...>:
>>
>>> why can't the compiler check the modification times
>>> on the actual files?
>>
>> Because, as someone else here has pointed out, there isn't always  
>> a file. When you generate code on the fly, you just pass a string  
>> to the groovy compiler. The resulting class(es) are not backed by  
>> files but they still have a compilation time.
>
> But it looks to me as though the relevant code only compares the  
> modification times if the source file exists - if the code has been  
> generated on the fly, then there won't be a source file, so there  
> will be nothing to compare. The problem is that isSourceNewer takes  
> a URL and a Class as an argument rather than two URLs - hence, it  
> seems to me that the easiest solution to this particular problem  
> would be to add a getClassFile method to GroovyResourceLoader, and  
> then compare the modification times on the two URLs, with  
> appropriate code to deal with a situation where one or other of the  
> files doesn't exist....

OK - so I decided I'd better try this to make sure it works, but it  
does...

I can now run Aaron's example repeatedly from within GroovyConsole  
without getting the exception.

To achieve this, I basically tweaked resolveToScript in the way I  
suggested - my first attempt wasn't quite right (I wasn't sure what  
to do if only objectURL was null), but the final result looks like this:

         URL sourceURL = null;
         URL objectURL = null;
         try {
             sourceURL = gcl.getResourceLoader().loadGroovySource(name);
             if ( sourceURL != null)
             {
                 objectURL = gcl.getResourceLoader().loadGroovyObject
(name);
             }
         } catch (MalformedURLException e) {
             // fall through and let the URL be null
         }
         if (sourceURL !=null) {
             if (type.isResolved() && objectURL != null) {
                 // if the file is not newer we don't want to recompile
                 if (!isSourceNewer(sourceURL,objectURL)) return true;
                 cachedClasses.remove(type.getName());
                 type.setRedirect(null);
             }
             SourceUnit su = compilationUnit.addSource(sourceURL);
             currentClass.getCompileUnit().addClassNodeToCompile
(type,su);
             return true;
         }
         // type may be resolved through the classloader before
         return type.isResolved();
     }

I rewrote isSourceNewer as follows:

     private long lastMod(URL url) throws IOException
     {
             long lastMod;

             // Special handling for file:// protocol, as  
getLastModified() often reports
             // incorrect results (-1)
             if (url.getProtocol().equals("file")) {
                 // Coerce the file URL to a File
                 String path = url.getPath().replace('/',  
File.separatorChar).replace('|', ':');
                 File file = new File(path);
                 lastMod = file.lastModified();
             }
             else {
                 URLConnection conn = url.openConnection();
                 lastMod = conn.getLastModified();
                 conn.getInputStream().close();
             }
             return lastMod;
     }

     private boolean isSourceNewer(URL source, URL object) {
         try {

             return lastMod(source) > lastMod(object);
         } catch (IOException e) {
             // if the stream can't be opened, let's keep the old  
reference
             return false;
         }
     }

and made some obvious changes to GroovyResourceLoader and  
GroovyClassLoader to support the new loadGroovyObject method - I also  
added a new getDefaultClassExtension method to CompilerConfiguration  
to allow refactoring of getSourceFile to getFile. The essential code  
is as follows, with getSourceFile renamed as getFile, which now takes  
an extra argument, the default file extension, which is obtained from  
the config object:

     private GroovyResourceLoader resourceLoader = new  
GroovyResourceLoader() {
         public URL loadGroovySource(final String filename) throws  
MalformedURLException {
             URL file = (URL) AccessController.doPrivileged(new  
PrivilegedAction() {
                 public Object run() {
                     return  getFile(filename,  
config.getDefaultScriptExtension());
                 }
             });
             return file;
         }

         public URL loadGroovyObject(final String filename) throws  
MalformedURLException
         {
             URL file = (URL) AccessController.doPrivileged(new  
PrivilegedAction() {
                 public Object run() {
                     return  getFile(filename,  
config.getDefaultClassExtension());
                 }
             });
             return file;        }
     };

    [...]

    private URL getFile(String name, String ext) {
         String filename = name.replace('.', '/') + ext;
    [...]
         // the rest is unchanged
    }

Anyway, it all seems to work - in particular, it passes all the test  
cases during the build, and it runs Aaron's example. However, as I  
said in my original message...

> Of course, there may be other reasons why the Groovy compiler needs  
> to initialize classes during compilation, but I don't see why it's  
> necessary in this particular situation.

I'll try and figure out how to generate a patch if someone confirms  
that my approach is reasonable...

BTW, I've not looked to see whether the duplicate code in  
GroovyClassLoader can also be rewritten in this way, but it should be  
possible, and that needs to be part of the patch too...

Thanks.

Robert

>
> Robert
>
> ---------------------------------------------------------------------
> To unsubscribe from this list please visit:
>
>    http://xircles.codehaus.org/manage_email
>


---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Re: Groovy runs code in static initializers during compile

by Jochen Theodorou :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Robert Stroud schrieb:
[...]

>         URL sourceURL = null;
>         URL objectURL = null;
>         try {
>             sourceURL = gcl.getResourceLoader().loadGroovySource(name);
>             if ( sourceURL != null)
>             {
>                 objectURL = gcl.getResourceLoader().loadGroovyObject(name);
>             }
>         } catch (MalformedURLException e) {
>             // fall through and let the URL be null
>         }

shouldn't sourceURL and objectURL be the same after this?

bye blackdrag

--
Jochen "blackdrag" Theodorou
Groovy Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

< Prev | 1 - 2 - 3 - 4 - 5 - 6 | Next >