Closed GoogleCodeExporter closed 9 years ago
I've investigated this a little and it seems like JavaAssist ignores the
removal of
the final modifier for inner classes (enum = static final class). This thread
may
provide some hints:
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4090308#4090308.
Original comment by johan.ha...@gmail.com
on 17 Mar 2009 at 2:06
Hope to get a solution for this as i have a similar situation with requirement
to
mock xmlbeans (generated) classes which contain public static final classes.
public interface NameNamingAttributeEnum
extends XmlString
{
public static final class Enum extends StringEnumAbstractBase
{
Original comment by rajmel...@googlemail.com
on 8 Apr 2009 at 12:28
Could the problem be that you're not allowed to remove the "final" keyword from
inner
Enums according the java specification? Seems like a long-shot though.
One (difficult) solution to the problem would be to create a substitute/replica
outer
Enum class and copy the structure of the inner Enum class and then delegate all
field access and method calls to this fictive class (just the way mocking of
final
system classes works now). Could work...
Original comment by johan.ha...@gmail.com
on 12 Apr 2009 at 10:56
Original comment by jan.kron...@gmail.com
on 27 Apr 2009 at 4:56
These are generated classes so found a way to use the realclasses rather than
mock
them at the moment.Lucky to get past at the moment.
Original comment by rajmel...@googlemail.com
on 27 Apr 2009 at 5:00
Original comment by johan.ha...@gmail.com
on 19 Sep 2009 at 7:41
Is this issue fixed in the 1.3.5 version? I get the same error message as above
when
I try to mock the Settings.Secure class in Android 1.6.
BR,
Christoffer
Original comment by toff...@gmail.com
on 14 Dec 2009 at 2:09
Could you try with Javassist 3.11 and see if it works?
Original comment by johan.ha...@gmail.com
on 14 Dec 2009 at 2:14
Replaced 3.10 with 3.11 and tried again. Same result as before unfortunately.
BR,
Christoffer
Original comment by toff...@gmail.com
on 14 Dec 2009 at 2:23
Ok thanks for trying it out. Last time I tried to investigate this my
conclusion was
that either it's not allowed to remove the final modifier or it was a bug in
Javassist. But I could of course very well be wrong. If you have any idea then
please
let us know.
Original comment by johan.ha...@gmail.com
on 14 Dec 2009 at 6:05
This works in JMockit so it should be legal from a byte-code perspective to
remove the
final modifier. I should bring this up with the Javassist team.
Original comment by johan.ha...@gmail.com
on 22 Dec 2009 at 7:36
JMockit does not remove the final modifier, though. It simply redefines method
bodies
belonging to the enum class. (The only case where JMockit changes modifiers is
when
mocking a native method.)
I suspect the solution will be the one you described in comment 3.
Original comment by rliesenf...@gmail.com
on 22 Dec 2009 at 12:29
Ah thanks for clarifying this. Just for curiosity, do you know if it ought to
be
possible to remove the final modifier of an enum? I don't see why you shouldn't
be
allowed to remove the final modifier from a static final inner class.
Original comment by johan.ha...@gmail.com
on 22 Dec 2009 at 6:57
I never tried to remove "final" before, but a quick experiment with a test
mocking
"MyEnum" gave me the following result when attempting to subtract ACC_ENUM from
the
"access" argument:
java.lang.UnsupportedOperationException: class redefinition failed: attempted
to
change the class modifiers
at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
So, I would say it definitely isn't supported.
Original comment by rliesenf...@gmail.com
on 23 Dec 2009 at 11:09
Actually, my previous comment is mistaken. Apart from the fact that it should
have been
ACC_FINAL instead of ACC_ENUM (which still causes the same exception to be
thrown), it
only applies to "class redefinition", which isn't the PowerMock approach.
During class
definition, it may be valid to remove "final" for an enum, but I don't really
know.
Original comment by rliesenf...@gmail.com
on 23 Dec 2009 at 11:33
Original comment by johan.ha...@gmail.com
on 22 Jul 2010 at 9:16
Issue 304 has been merged into this issue.
Original comment by johan.ha...@gmail.com
on 6 Jan 2011 at 12:16
I have enclosed the following patch that fixes this issue within PowerMock.
Included in the patch are 3 test cases that without this patch fail to work.
Tested on Sun/Oracle Linux x86_64 1.6.0_21.
The change comes down to the InnerClasses attribute [1] in the class byte code.
It seems that even though the class proper is marked as non-final, the JVM
would see that the class should be final based upon the info in this attribute
and as a result the class would remain final. The patch looks for the
InnerClasses attribute on each class, and if the attribute exists, resets the
final access modifier for the class being edited.
Patch was made against svn revision 1570 at
http://powermock.googlecode.com/svn/trunk.
[1]
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#80000
Original comment by nairb...@gmail.com
on 21 Jan 2011 at 12:36
Attachments:
Awesome!! I've applied the patch and committed it to trunk. I've also verified
that it works for private static final inner classes.
Thanks A LOT for your help. As you may know this has been an issue for so long
and it's really nice that it has finally been resolved.
Original comment by johan.ha...@gmail.com
on 21 Jan 2011 at 7:37
Original comment by johan.ha...@gmail.com
on 21 Jan 2011 at 8:32
Excellent! (I just updated my comparison matrix to reflect this.)
Original comment by rliesenf...@gmail.com
on 2 Mar 2011 at 8:06
Original issue reported on code.google.com by
DanFabul...@gmail.com
on 12 Mar 2009 at 8:02Attachments: