ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Conor MacNeill" <co...@cortexebusiness.com.au>
Subject class static initialization and classloaders
Date Thu, 10 May 2001 11:53:01 GMT
Hi,

I have been looking at bug 1613 which is a summary of two other bugs (1066
and 1362). The synopsis for these is "AntClassLoader doesn't run static
initializer blocks". I do not believe it is the class loader's
responsibility to run static initializer blocks. In fact, there is no way
that I know to explicitly run these from Java code. I have done some
investigations using the example code  from bug 1362. I wrote a third class
C.java which I include below.

I have been running this code outside of Ant to ensure that the fundamental
issue is not Ant related. The code below lets me run code similar to that
used by Ant but with two different strategies for loading the class "t.B".
The results are as follows:

F:\oss_ssh\JakartaSSH\bugs\antbug1362>java t.C 1
A static initialization
MAIN
I am an A.

F:\oss_ssh\JakartaSSH\bugs\antbug1362>java t.C 2
A static initialization
java.lang.Exception
        at t.B.<clinit>(B.java:6)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:120)
        at t.C.test2(C.java:37)
        at t.C.main(C.java:12)
B static initialization
MAIN
I am a B.

In the first approach, B's initializer does not run. The second approach
does run the initializer. The exception trace in the second run is just to
see a stacktrace of where the initializer is being run from. The results
are pretty surprising. When you use reflection on a class loaded by a
classloader (no AntClassLoader in sight), the static initializer is not
run. If you look at the comment "// try to get static initializers to run",
I have been trying various things in that block to get the static
initializers to run. The only thing which has worked has been to call
newInstance(). It doesn't matter if there is no zero-argument constructor,
the static initializers still get run.

So, that may be a hacky workaround to this problem. Any other ideas or
experience, anything I am missing here? I am using 1.3.0-C on NT and
1.2.2_005.

Conor


------------------------------------------------
package t;

import java.lang.reflect.*;

public class C
{
    public static void main(String [] args){
        if (args[0].equals("1")) {
            test1(args);
        }
        else {
            test2(args);
        }
    }

    static public void test1(String [] args) {
        // invoke B with reflection
        try {
            final Object[] argument = {args};
            final Class[] param = { Class.forName("[Ljava.lang.String;") };
            Class bClass = C.class.getClassLoader().loadClass("t.B");
            final Method main = bClass.getMethod("main", param);
            try {
                // try to get static initializers to run
            }
            catch (Exception e) {e.printStackTrace();}
            main.invoke(null, argument);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    static public void test2(String [] args) {
        // invoke B with reflection
        try {
            Class bClass = Class.forName("t.B");
            final Object[] argument = {args};
            final Class[] param = { Class.forName("[Ljava.lang.String;") };
            final Method main = bClass.getMethod("main", param);
            main.invoke(null, argument);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}






Mime
View raw message