Details
-
Bug
-
Status: Open
-
Minor
-
Resolution: Unresolved
-
5.5.0
-
None
-
None
Description
Plastic replaces the original constructor and moves the original instruction to the "initializeInstance" method in the new constructor. If any final field is present in the class, a "java.lang.IllegalAccessError" will be thrown.
Due to [JDK-8157181|https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8157181], it was possible to set final fields outside of "<init>", which is not allowed in the Java Language Specification
The problems originates from org.apache.tapestry5.internal.plastic.PlasticClassImpl.convertOriginalConstructorToMethod() in line 746.
To fix the problem, the "putfield" opcodes for final field should not be in the initializeInstance method, and should be called directly in "<init>" by the constructorBuilder.
I came up with the following code. Even though without a working project setup, it's hard to get it right.
private void stripOutPutfieldInstructions(MethodNode cons) { InsnList ins = cons.instructions; ListIterator li = ins.iterator(); while (li.hasNext()) { AbstractInsnNode node = (AbstractInsnNode) li.next(); if (node.getOpcode() == Opcodes.PUTFIELD) { FieldInsnNode fieldNode = (FieldInsnNode) node; constructorBuilder.loadThis().putField(className, fieldNode.name, ???); // Remove the PUTFIELD li.remove(); break; } } }
This would fix the field access problem but could introduce subtle bugs due to manipualting the call order of the original constructor instructions.
Instead, ALL remaining instructions need to be added to the constructorBuilder, and not moved to "initializeInstance".
I'm not that "fluent" in Plastic, or how it exactly creates classes/instances, so all of this might not work as I think it could. But hopefully, it helps to better understand the problem.
Most likely older versions of Tapestry are affected, too, because the JDK bug was backported to older versions.