Issue Details (XML | Word | Printable)

Key: LANG-76
Type: Bug Bug
Status: Reopened Reopened
Priority: Major Major
Assignee: Unassigned
Reporter: Igor Laberov
Votes: 3
Watchers: 2
Operations

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

[lang] EnumUtils.getEnum() doesn't work well in 1.5

Created: 15/Sep/05 06:20 PM   Updated: 16/Aug/09 07:15 AM
Component/s: None
Affects Version/s: 2.1
Fix Version/s: 2.x

Time Tracking:
Not Specified

Environment:
Operating System: other
Platform: Other
Issue Links:
Duplicate
 

Bugzilla Id: 36666


 Description  « Hide
Hi,
I encountered with problem using EnumUtils.getEnum() in 1.5. It appears that my
Enum class should be accessed first so constructor will be called. In 1.4 it was
enough to have myClass.class, so all static members were initialized. In 1.5 it
doesn't work.

I noticed that static members are not initialized anymore while acessing to
class definition. See the code
public class Test {
public static final class TT{
public static final TT one = new TT();

private TT(){ System.out.println("Called TT" ); }
}

public static void main(String[] args) { Class cl = TT.class; // System.out.println( TT.one); // System.out.println(TT.class.isAssignableFrom(String.class)); }
}
In 1.4 constructor of TT is called, while in 1.5 is not.

Actually, according to the spec
(http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#57946),
this is right behavior of Java.
Unfortunately, I didn't succeded to think about good solution..
P.s. I know that in 1.5 we have enum built-in, but it is not the same, and we
try to move to 1.5 without too much changes



 All   Comments   Work Log   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Igor Laberov added a comment - 15/Sep/05 11:03 PM
It is possible to load Enum static fields using code below:

Field[] fields = enumCl.getFields();
if(fields.length>0){
try { fields[0].get(null); //get value of first static - actual access to this class instance } catch (Exception e) { log.trace("Can't access static field of " + enumCl); }
}


Henri Yandell added a comment - 08/Jun/06 03:42 PM
In an effort to get 2.2 out sooner rather than later, I'm assiging all the Enum issues to 2.3. There's been no work on them currently and might be best to focus on them in a 2.3 release instead of trying to squeeze them into the 2.2 release.

Hopefully this will keep the 2.3 release scope pretty tight.



Michael Nascimento Santos added a comment - 14/Aug/06 03:48 PM
I've filed a RFE for solving the problem in the correct way: <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6459208">http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6459208</a>

Henri Yandell added a comment - 24/Oct/06 07:57 PM
Apologies for how long it's taken to get around to this issue - largely because it doesn't seem like an issue with much of a solution. Even if the RFE is solved (and it looks like it might be someday), I suspect it's unlikely it would be backported to Java 5.0.

If I'm understanding things correctly, the problem is that in 1.4 Igor had code that just said IgorEnum.class. This initialised all the constant enum declarations within his IgorEnum class - which I presume was necessary for some reason (ie: he couldn't just say 'IgorEnum.ONE' and have it work).

The work-around would appear to be to create a static enumInitialize() method within the IgorEnum class that looks much like this:

static void enumInitialize() { TT tmp = ONE; // or whatever kind of setup call is needed }

Then change the 'Class tmp = IgorEnum.class' to 'IgorEnum.enumInitialize()'.

I suspect I'm missing something in the complexity behind why the IgorEnum.class call was desirable in the first place.


Henri Yandell added a comment - 06/Dec/06 09:02 AM
I can't see this being fixed in 2.3 (or ever). Assigning to 3.0 for the moment.

Henri Yandell added a comment - 25/Jan/07 02:58 AM
Alternative workaround from Peter Knuts (received via email):

I have a work around that can be used to mitigate the problem that was not suggested previously.
The solution is simpler than the previously suggested workarounds.

Define a static method inside the defining enum class to load the enum, ex:

public class TestEnum extends Enum {
private TestEnum(String name) { super(name); }
public static final TestEnum VALUE_ONE = new TestEnum("Value one");

public static TestEnum getEnum(String name) { return (TestEnum) EnumUtils.getEnum(TestEnum.class, name); }
}

This works fine and the class will be loaded due to the static method call
Java Language Specification:
A class or interface type T will be initialized immediately before the first occurance of any one of the following:

  • T is a class and an instance of T is created
  • T is a class and a static method declared by T is invoked.
    ...

The downside of this is that the method can not be implemented in a common super class but needs to be (re)implemented in every enum class that needs this capability (also true for other EnumUtils methods like getEnumList etc).

The upside is that the calling side will be simpler:
Before: (TestEnum) EnumUtils.getEnum(TestEnum.class, name);
After: TestEnum.getEnum(name);


Marcus Schulte added a comment - 23/Jun/07 10:50 AM
I think EnumUtils.getEnum() should force class initialization, e.g. by calling

Class.forName(enumClass.getFullName(), true, enumClass.getClassLoader())

Otherwise it will simply not reliably do what it is advertised to do. Plus it will spare people a hard-to-find bug popping up after migrating their code to 5.0.


Joe Kelly added a comment - 26/Jun/07 07:27 PM
I like Marcus Schulte's suggestion. EnumUtils.getEnum() should force class initialization.

Henri Yandell added a comment - 03/Nov/07 08:09 AM
Bringing forward into 2.4 for consideration again.

Paul Benedict added a comment - 09/Nov/07 08:22 AM
Relying on .class to perform class initialization is, to the best of my knowledge, a well-known behavior of past JVMs but also an undocumented feature. Unless someone can show from a JVM spec, that referencing .class must perform class initialization, then I strongly believe this issue is based on an undocumented developer assumption. The "problem" in JDK 5 is therefore neither right or wrong and I recommend this as a WONTFIX.

If you want to force initialization, create a static initialization block (static { }) and do what needs to be done there.


Ben Speakmon added a comment - 12/Nov/07 08:13 PM
Gotta agree with Paul. 1.5's behavior is to spec, so it's correct by definition. Since this Enum is for pre-1.5 users, I don't see a benefit to the work involved reconciling it with 1.5. I'd say wontfix.

Henri Yandell added a comment - 12/Nov/07 08:30 PM
Marking as wontfix as I don't see it being likely that anything will be done here.

Joe's suggestion is interesting, and if anyone would like to explore that, prove that it solves the problem and attach as a patch, then please reopen.


Lew Bloch added a comment - 14/Aug/09 09:34 PM
It is egregious that the project refuses to fix a bug caused by its own intentional violation of the Java Language Specification (JLS). It is also strange that the powers that be think this library will never be used in a Java 5+ environment - there are use cases for having a well-thought-out typesafe enumeration that can do things not available to standard 'enum' classes, e.g., inherit from other enumerations or interoperate with legacy pre-1.5 systems. This shunning of responsibility is a saddening disappointment coming from an Apache project, especially one so fundamental and widely used as commons-lang. Palming the bug off as "[r]elying on ... an undocumented feature" is especially disingenuous. That classes used to initialize on references to the 'class' literal was a bug, not a feature, and contravened the explicit statement in the JLS second edition, s.12.4.1: "A class or interface will not be initialized under any other circumstance." (Statement follows list of class-initialization triggers that does not include reference to the 'class' literal.) For shame.

Henri Yandell added a comment - 16/Aug/09 07:15 AM
Reopening issue based on Lew's diatribe. Fix version will be set to 2.x. I don't expect to see such a release happen and this code has been removed from 3.0, however if a 2.x release does happen then I want to make sure this is up for consideration along with the other Enum issues.

Plus it will be easier to find the problem if it is in an open issue than a closed issue.