JDK 21 |
---|
21 b21Fixed |
Blocks :
|
|
CSR :
|
|
Duplicate :
|
|
Duplicate :
|
|
Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
JDK-8308450 :
|
A DESCRIPTION OF THE PROBLEM : Chapter 13.1 in the JLS mentions: 11. A construct emitted by a Java compiler must be marked as synthetic if it does not correspond to a construct declared explicitly or implicitly in source code, unless the emitted construct is a class initialization method and 12. A construct emitted by a Java compiler must be marked as mandated if it corresponds to a formal parameter declared implicitly in source code For parameters, this information is stored in the MethodParameters attribute. However, this attribute is only emitted when compiling with the -parameters flag or if the method is a canonical record constructor. This behavior can be observed by either looking at the produced class files using javap, or by using the Parameter#isImplicit()/isSynthetic() methods. Additional context: https://mail.openjdk.org/pipermail/compiler-dev/2022-May/019783.html and https://mail.openjdk.org/pipermail/compiler-dev/2022-June/019924.html I'm able to provide a fix for this. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Compile the code below with javac without -parameters flag. Run the code with java A. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - ---------- Executable: A$Inner Parameter at position 0 parameter.getType() = class A parameter.isImplicit() = true ---------- ---------- Executable: A$1 Parameter at position 0 parameter.getType() = class A parameter.isImplicit() = true ---------- ---------- Executable: valueOf Parameter at position 0 parameter.getType() = class java.lang.String parameter.isImplicit() = true ---------- ---------- Executable: A$R Parameter at position 0 parameter.getType() = int parameter.isImplicit() = true Parameter at position 1 parameter.getType() = float parameter.isImplicit() = true ---------- ---------- Executable: A$E Parameter at position 0 parameter.getType() = class java.lang.String parameter.isSynthetic() = true Parameter at position 1 parameter.getType() = int parameter.isSynthetic() = true ---------- ACTUAL - ---------- Executable: A$Inner Parameter at position 0 parameter.getType() = class A parameter.isImplicit() = false ---------- ---------- Executable: A$1 Parameter at position 0 parameter.getType() = class A parameter.isImplicit() = false ---------- ---------- Executable: valueOf Parameter at position 0 parameter.getType() = class java.lang.String parameter.isImplicit() = false ---------- ---------- Executable: A$R Parameter at position 0 parameter.getType() = int parameter.isImplicit() = false Parameter at position 1 parameter.getType() = float parameter.isImplicit() = false ---------- ---------- Executable: A$E Parameter at position 0 parameter.getType() = class java.lang.String parameter.isSynthetic() = false Parameter at position 1 parameter.getType() = int parameter.isSynthetic() = false ---------- ---------- BEGIN SOURCE ---------- import java.lang.reflect.Executable; import java.lang.reflect.Parameter; public class A { public static void main(String[] args) throws Exception { // implicit print(Inner.class.getDeclaredConstructors()[0], true); print(A.class.getDeclaredField("anon").get(new A()).getClass().getDeclaredConstructors()[0], true); print(E.class.getDeclaredMethod("valueOf", String.class), true); print(R.class.getDeclaredConstructors()[0], true); // synthetic print(E.class.getDeclaredConstructors()[0], false); } static void print(Executable executable, boolean implicit) { System.out.println("----------"); System.out.println("Executable: " + executable.getName()); Parameter[] parameters = executable.getParameters(); for (int i = 0; i < parameters.length; i++) { Parameter parameter = parameters[i]; System.out.println("Parameter at position " + i); System.out.println("parameter.getType() = " + parameter.getType()); if (implicit) { System.out.println("parameter.isImplicit() = " + parameter.isImplicit()); } else { System.out.println("parameter.isSynthetic() = " + parameter.isSynthetic()); } } System.out.println("----------"); } class Inner { Inner() {} } Inner anon = new Inner() {}; enum E {} record R(int a, float b) { public R {} } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : Use the -parameters flag for compilation (does not work for the record ctor). FREQUENCY : always
|