fork download
  1. import java.util.*;
  2. import java.lang.reflect.*;
  3.  
  4. enum Color {RED, BLUE, GREEN};
  5.  
  6. class Example {
  7. public static void main(String[] args) throws Exception {
  8. // use the Field at least once so it creates and caches accessors
  9. // with the final modifier
  10. System.out.println(Arrays.toString((Object[]) getValuesField(Color.class).get(null)));
  11.  
  12. // now throws IllegalAccessException, because removing
  13. // the final modifier has no effect (IllegalAccessException
  14. // is thrown by the field accessor)
  15. try {
  16. setEnumsArray(Color.class, Color.RED, Color.RED, Color.RED);
  17. } catch (IllegalAccessException x) {
  18. System.out.println(x);
  19. System.out.println(" at " + x.getStackTrace()[0]);
  20. }
  21.  
  22. // clear accessors
  23. clearFieldAccessors(getValuesField(Color.class));
  24. // now it works
  25. setEnumsArray(Color.class, Color.RED, Color.RED, Color.RED);
  26.  
  27. System.out.println(Arrays.toString(Color.values()));
  28. }
  29.  
  30. static Field getValuesField(Class<?> c) throws Exception {
  31. Field f = c.getDeclaredField("$VALUES");
  32. f.setAccessible(true);
  33. return f;
  34. }
  35.  
  36. static <E extends Enum<E>> void setEnumsArray(Class<E> ec, E... e) throws Exception {
  37. Field field = getValuesField(ec);
  38. Field modifiersField = Field.class.getDeclaredField("modifiers");
  39. field.setAccessible(true);
  40. modifiersField.setAccessible(true);
  41. modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
  42. field.set(ec, e);
  43. }
  44.  
  45. static void clearFieldAccessors(Field field)
  46. throws ReflectiveOperationException {
  47. Field fa = Field.class.getDeclaredField("fieldAccessor");
  48. fa.setAccessible(true);
  49. fa.set(field, null);
  50.  
  51. Field ofa = Field.class.getDeclaredField("overrideFieldAccessor");
  52. ofa.setAccessible(true);
  53. ofa.set(field, null);
  54.  
  55. Field rf = Field.class.getDeclaredField("root");
  56. rf.setAccessible(true);
  57. Field root = (Field) rf.get(field);
  58. if (root != null) {
  59. clearFieldAccessors(root);
  60. }
  61. }
  62. }
Success #stdin #stdout 0.1s 27872KB
stdin
Standard input is empty
stdout
[RED, BLUE, GREEN]
java.lang.IllegalAccessException: Can not set static final [LColor; field Color.$VALUES to [LColor;
    at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
[RED, RED, RED]