History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: GROOVY-2135
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Jochen Theodorou
Reporter: Daniel.Sun
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
groovy

failed to reference an instance defined in enum class with the syntax like Planet.MERCURY

Created: 23/Sep/07 05:11 AM   Updated: 23/Jun/08 06:14 AM
Component/s: None
Affects Version/s: 1.1-beta-3
Fix Version/s: 1.5.7, 1.6-beta-2

Time Tracking:
Not Specified

Environment: Groovy1.1 rc1, jdk6u2, winxp


 Description  « Hide
I failed to run the following code with groovy1.1 rc1
Planet.groovy
public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7),
    PLUTO   (1.27e+22,  1.137e6);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    public double mass()   { return mass; }
    public double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    public double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    public double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
    public String toString() {
        return mass + ", " + radius;
    }
    
    public static void main(String[] args) {
    	System.out.println(Planet.MERCURY);
    }
}

Groovy complains:
Exception thrown: java.lang.InstantiationException: Planet

java.lang.InstantiationException: Planet
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:366)
at groovy.lang.GroovyShell.parse(GroovyShell.java:500)
at groovy.lang.GroovyShell.parse(GroovyShell.java:480)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:458)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:400)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:64)
at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:537)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:772)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:614)
at org.codehaus.groovy.runtime.Invoker.invokePogoMethod(Invoker.java:98)
at org.codehaus.groovy.runtime.Invoker.invokeMethod(Invoker.java:79)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:74)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:158)
at groovy.ui.Console$_runScript_closure10.doCall(Console.groovy:681)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:64)
at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:537)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:224)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnCurrentN(ScriptBytecodeAdapter.java:66)
at groovy.ui.Console$_runScript_closure10.doCall(Console.groovy)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:64)
at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:537)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:224)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:614)
at groovy.lang.Closure.call(Closure.java:292)
at groovy.lang.Closure.call(Closure.java:287)
at groovy.lang.Closure.run(Closure.java:368)
at java.lang.Thread.run(Thread.java:619)



 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Daniel.Sun - 23/Sep/07 05:13 AM
I am using groovy1.1 beta3,
sorry for my carelessness.

Daniel.Sun - 23/Sep/07 05:20 AM
The code runs well with jdk6u2

the result of executing is:
3.303E23, 2439700.0

failed to run the following code with groovy1.1beta3 too, but run with jdk6u2 well :
System.out.println(Enum.valueOf(Planet.class, "MERCURY"));


Alexandru Popescu - 05/Oct/07 04:44 PM
As far as I can say the problem comes from the fact that the generated $INIT method is trying to invoke an enum constructor reflectively, and this is not allowed for enums.
And I think it is the last part of the $INIT implementation that is performing this op (just before the CHECKCAST).

./alex

.w( the_mindstorm )p.


Alexandru Popescu - 05/Oct/07 06:20 PM
Unfortunately, I don't know how to fix it, but think that the problem comes from the following:

183 aload_1
184 invokestatic #111 <org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType>
187 checkcast #2 <Planet>
190 areturn

which instead of invoking castToType(new enum, Planet) it invokes castToType(methods_args, Planet) where method_args are the args to $INIT method.

./alex

.w( the_mindstorm )p.


Alexandru Popescu - 05/Oct/07 06:40 PM
Well, I have found a hack but it is for sure not the fix:

line: 1802 ACG:
original:

//load "this"
if (constructorNode!=null) { mv.visitVarInsn(ALOAD, 0); } else { mv.visitTypeInsn(NEW, BytecodeHelper.getClassInternalName(callNode)); }

new:

boolean newObj= false;
//load "this"
if (constructorNode!=null) { mv.visitVarInsn(ALOAD, 0); } } else { mv.visitTypeInsn(NEW, BytecodeHelper.getClassInternalName(callNode)); mv.visitInsn(DUP); mv.visitVarInsn(ASTORE, 4); newObj= true; }

I am storing the new created object so I can load it at the end of this method.

At the end of the ACG.visitSpecialConstructorCall if(newObj) mv.visitVarInsn(ALOAD, 4);

(and as I said I am aware that this is just a hack).


Alexandru Popescu - 05/Oct/07 06:43 PM
I have done some research on this, but I am pretty sure you'll have a better solution.

Jochen Theodorou - 11/Oct/07 07:50 PM
this was basically the same issue as GROOVY-2137

Daniel.Sun - 13/Oct/07 11:06 PM
groovy> public enum Planet {
groovy> MERCURY (3.303e+23, 2.4397e6),
groovy> VENUS (4.869e+24, 6.0518e6),
groovy> EARTH (5.976e+24, 6.37814e6),
groovy> MARS (6.421e+23, 3.3972e6),
groovy> JUPITER (1.9e+27, 7.1492e7),
groovy> SATURN (5.688e+26, 6.0268e7),
groovy> URANUS (8.686e+25, 2.5559e7),
groovy> NEPTUNE (1.024e+26, 2.4746e7),
groovy> PLUTO (1.27e+22, 1.137e6);
groovy>
groovy> private final double mass; // in kilograms
groovy> private final double radius; // in meters
groovy> Planet(double mass, double radius) { groovy> this.mass = mass; groovy> this.radius = radius; groovy> }
groovy> public double mass() { return mass; }
groovy> public double radius() { return radius; }
groovy>
groovy> // universal gravitational constant (m3 kg-1 s-2)
groovy> public static final double G = 6.67300E-11;
groovy>
groovy> public double surfaceGravity() { groovy> return G * mass / (radius * radius); groovy> }
groovy> public double surfaceWeight(double otherMass) { groovy> return otherMass * surfaceGravity(); groovy> }
groovy> public String toString() { groovy> return mass + ", " + radius; groovy> }
groovy>
groovy> public static void main(String[] args) { groovy> System.out.println(Planet.MERCURY); groovy> }
groovy> }

Exception thrown: java.lang.InstantiationException: Planet

java.lang.InstantiationException: Planet


Daniel.Sun - 13/Oct/07 11:14 PM
but the following code is ok.
public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7),
    PLUTO   (1.27e+22,  1.137e6);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    public double mass()   { return mass; }
    public double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    public double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    public double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
    public String toString() {
        return mass + ", " + radius;
    }

}

System.out.println(Planet.MERCURY)

Jochen Theodorou - 02/Nov/07 09:41 AM
I really have problems reproducing this issue... could someone take the newest version and test it again please?

Daniel.Sun - 03/Nov/07 12:41 AM
groovy> public enum Planet {
groovy>     MERCURY (3.303e+23, 2.4397e6),
groovy>     VENUS   (4.869e+24, 6.0518e6),
groovy>     EARTH   (5.976e+24, 6.37814e6),
groovy>     MARS    (6.421e+23, 3.3972e6),
groovy>     JUPITER (1.9e+27,   7.1492e7),
groovy>     SATURN  (5.688e+26, 6.0268e7),
groovy>     URANUS  (8.686e+25, 2.5559e7),
groovy>     NEPTUNE (1.024e+26, 2.4746e7),
groovy>     PLUTO   (1.27e+22,  1.137e6);
groovy>     private final double mass;   // in kilograms
groovy>     private final double radius; // in meters
groovy>     Planet(double mass, double radius) {
groovy>         this.mass = mass;
groovy>         this.radius = radius;
groovy>     }
groovy>     public double mass()   { return mass; }
groovy>     public double radius() { return radius; }
groovy>     // universal gravitational constant  (m3 kg-1 s-2)
groovy>     public static final double G = 6.67300E-11;
groovy>     public double surfaceGravity() {
groovy>         return G * mass / (radius * radius);
groovy>     }
groovy>     public double surfaceWeight(double otherMass) {
groovy>         return otherMass * surfaceGravity();
groovy>     }
groovy>     public String toString() {
groovy>         return mass + ", " + radius;
groovy>     }
groovy>     
groovy>     public static void main(String[] args) {
groovy>         System.out.println(Planet.MERCURY);
groovy>     }
groovy> }

Exception thrown: java.lang.InstantiationException: Planet

java.lang.InstantiationException: Planet
	at java.lang.Class.newInstance0(Class.java:340)
	at java.lang.Class.newInstance(Class.java:308)
	at org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:382)
	at groovy.lang.GroovyShell.parse(GroovyShell.java:500)
	at groovy.lang.GroovyShell.parse(GroovyShell.java:480)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:458)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:400)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:56)
	at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:538)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:803)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:643)
	at org.codehaus.groovy.runtime.Invoker.invokePogoMethod(Invoker.java:98)
	at org.codehaus.groovy.runtime.Invoker.invokeMethod(Invoker.java:79)
	at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:69)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:170)
	at groovy.ui.Console$_runScriptImpl_closure10.doCall(Console.groovy:836)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:56)
	at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:538)
	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:243)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnCurrentN(ScriptBytecodeAdapter.java:78)
	at groovy.ui.Console$_runScriptImpl_closure10.doCall(Console.groovy)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:56)
	at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:538)
	at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:243)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:643)
	at groovy.lang.Closure.call(Closure.java:291)
	at groovy.lang.Closure.call(Closure.java:286)
	at groovy.lang.Closure.run(Closure.java:367)
	at java.lang.Thread.run(Thread.java:619)

Groovy1.1RC2, JDK6u3, WinXP

Jochen, I hope these info will be helpful


Jochen Theodorou - 03/Nov/07 05:24 PM
ah, I guess now I get it... I was misleaded by the issue title... The problem isn't the enum itself, the problem is code trying the excute the enum as script. The problem would then be in InvokerHelper#createScript. It is no problem of the Enum implementation in Groovy at all, it is just a problem with the restriction of the reflection API for creating instances of Enum classes. Maybe I should go even one more step further and say that it is only a problem of GroovyShell, because GroovyShell seems to assume, that every class is convertable to a script. And that is not true for Enums. If you use your example for the groovy command from command line it will work without problem, the problem is only from GroovyShell.

We have now different choices...
1) let GroovyShell or InvokerHelper#createScript check for the enum class and let it react different in that case
2) say enums can't be used in a GroovyShell


Jochen Theodorou - 15/Nov/07 08:17 AM
I changed the priority, since it is no critical bug- True, it won't work in the console, but it will work in the groovy language

Jason Dillon - 04/May/08 03:57 AM
Is this still an issue? I just tried this with groovysh 1.6-beta-2-SNAPSHOT and it works with no issues.

Also not sure this is a groovysh bug...

Anyways, seems to be fixed to me, can you please close this issue?


Daniel.Sun - 04/May/08 05:25 AM
I ran the code again in the groovy console with groovy1.6beta1.
the issue still exists

groovy> public enum Planet {
groovy> MERCURY (3.303e+23, 2.4397e6),
groovy> VENUS (4.869e+24, 6.0518e6),
groovy> EARTH (5.976e+24, 6.37814e6),
groovy> MARS (6.421e+23, 3.3972e6),
groovy> JUPITER (1.9e+27, 7.1492e7),
groovy> SATURN (5.688e+26, 6.0268e7),
groovy> URANUS (8.686e+25, 2.5559e7),
groovy> NEPTUNE (1.024e+26, 2.4746e7),
groovy> PLUTO (1.27e+22, 1.137e6);
groovy> private final double mass; // in kilograms
groovy> private final double radius; // in meters
groovy> Planet(double mass, double radius) { groovy> this.mass = mass; groovy> this.radius = radius; groovy> }
groovy> public double mass() { return mass; }
groovy> public double radius() { return radius; }
groovy> // universal gravitational constant (m3 kg-1 s-2)
groovy> public static final double G = 6.67300E-11;
groovy> public double surfaceGravity() { groovy> return G * mass / (radius * radius); groovy> }
groovy> public double surfaceWeight(double otherMass) { groovy> return otherMass * surfaceGravity(); groovy> }
groovy> public String toString() { groovy> return mass + ", " + radius; groovy> }
groovy>
groovy> public static void main(String[] args) { groovy> System.out.println(Planet.MERCURY); groovy> }
groovy> }

Exception thrown: java.lang.InstantiationException: Planet

java.lang.InstantiationException: Planet


Paul King - 04/May/08 05:31 AM
Removed groovysh as component as I think this is a GroovyShell not groovysh issue. I still get the following on 1.5.6 and 1.6-beta1 when running the original example in GroovyConsole: Exception thrown: java.lang.InstantiationException: Planet.

Jochen Theodorou - 08/May/08 12:03 PM
doesn't groovysh use GroovyShell? I added that component, because of the comment from November 3rd... I would also like to reassign this issue to someone else

Paul King - 21/Jun/08 06:08 AM
I just tried this again on trunk in both groovyConsole and groovysh and the problem seems to have gome away. Anyone object to closing this?

Paul King - 23/Jun/08 06:14 AM
Please reopen if you find any issues.