Skip to content

Commit 6de1fc6

Browse files
committedJun 28, 2024
Conflicting code reflection fields for method overrides
Reviewed-by: mcimadamore, psandoz
1 parent abc426e commit 6de1fc6

File tree

5 files changed

+122
-4
lines changed

5 files changed

+122
-4
lines changed
 

‎src/java.base/share/classes/java/lang/reflect/Method.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import java.util.StringJoiner;
5555

5656
import static java.lang.reflect.code.op.CoreOp.*;
57+
import java.lang.reflect.code.type.MethodRef;
5758

5859
/**
5960
* A {@code Method} provides information about, and access to, a single method
@@ -277,7 +278,13 @@ public Optional<FuncOp> getCodeModel() {
277278

278279
private Optional<FuncOp> createCodeModel() {
279280
Class<?> dc = getDeclaringClass();
280-
String fieldName = getName() + "$" + "op";
281+
char[] sig = MethodRef.method(this).toString().toCharArray();
282+
for (int i = 0; i < sig.length; i++) {
283+
switch (sig[i]) {
284+
case '.', ';', '[', '/': sig[i] = '$';
285+
}
286+
}
287+
String fieldName = new String(sig) + "$" + "op";
281288
Field f;
282289
try {
283290
f = dc.getDeclaredField(fieldName);

‎src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ReflectMethods.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ public void visitMethodDef(JCMethodDecl tree) {
191191
}
192192
// create a static final field holding the op' string text.
193193
// The name of the field is foo$op, where 'foo' is the name of the corresponding method.
194-
classOps.add(opFieldDecl(tree.name, tree.getModifiers().flags, funcOp));
194+
classOps.add(opFieldDecl(methodName(bodyScanner.symbolToErasedMethodRef(tree.sym)), tree.getModifiers().flags, funcOp));
195195
} catch (UnsupportedASTException ex) {
196196
// whoops, some AST node inside the method body were not supported. Log it and move on.
197197
log.note(ex.tree, Notes.MethodIrSkip(tree.sym.enclClass(), tree.sym, ex.tree.getTag().toString()));
@@ -354,6 +354,16 @@ Name lambdaName() {
354354
return names.fromString("lambda").append('$', names.fromString(String.valueOf(lambdaCount++)));
355355
}
356356

357+
Name methodName(MethodRef method) {
358+
char[] sigCh = method.toString().toCharArray();
359+
for (int i = 0; i < sigCh.length; i++) {
360+
switch (sigCh[i]) {
361+
case '.', ';', '[', '/' -> sigCh[i] = '$';
362+
}
363+
}
364+
return names.fromChars(sigCh, 0, sigCh.length);
365+
}
366+
357367
private JCVariableDecl opFieldDecl(Name prefix, long flags, CoreOp.FuncOp op) {
358368
VarSymbol opFieldSym = new VarSymbol(flags | Flags.STATIC | Flags.FINAL | Flags.SYNTHETIC,
359369
prefix.append('$', names.fromString("op")),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import org.testng.Assert;
25+
import org.testng.annotations.Test;
26+
import org.testng.annotations.DataProvider;
27+
28+
import java.lang.invoke.MethodHandles;
29+
import java.lang.reflect.InvocationTargetException;
30+
import java.lang.reflect.Method;
31+
import java.lang.reflect.code.interpreter.Interpreter;
32+
import java.lang.reflect.code.op.CoreOp;
33+
import java.lang.runtime.CodeReflection;
34+
import java.util.*;
35+
import java.util.stream.Stream;
36+
37+
/*
38+
* @test
39+
* @run testng TestOverloads
40+
*/
41+
42+
public class TestOverloads {
43+
44+
@CodeReflection
45+
static int f() {
46+
return 0;
47+
}
48+
49+
@CodeReflection
50+
static int f(int i) {
51+
return 1;
52+
}
53+
54+
@CodeReflection
55+
static int f(Integer i) {
56+
return 2;
57+
}
58+
59+
@CodeReflection
60+
static int f(Object o) {
61+
return 3;
62+
}
63+
64+
@CodeReflection
65+
static int f(List<Integer> l) {
66+
return 4;
67+
}
68+
69+
@CodeReflection
70+
static int f(List<Integer> l, Object o) {
71+
return 5;
72+
}
73+
74+
@DataProvider(name = "testData")
75+
public static Object[][] testData() {
76+
return new Object[][]{
77+
new Object[] {new Class[]{}, new Object[]{}},
78+
new Object[] {new Class[]{int.class}, new Object[]{-1}},
79+
new Object[] {new Class[]{Integer.class}, new Object[]{-1}},
80+
new Object[] {new Class[]{Object.class}, new Object[]{"hello"}},
81+
new Object[] {new Class[]{List.class}, new Object[]{List.of()}},
82+
new Object[] {new Class[]{List.class, Object.class}, new Object[]{List.of(), -1}}
83+
};
84+
}
85+
86+
@Test(dataProvider = "testData")
87+
public static void testOverloads(Class<?>[] paramTypes, Object[] params) {
88+
try {
89+
Class<TestOverloads> clazz = TestOverloads.class;
90+
Method method = clazz.getDeclaredMethod("f", paramTypes);
91+
CoreOp.FuncOp f = method.getCodeModel().orElseThrow();
92+
var res1 = Interpreter.invoke(MethodHandles.lookup(), f, params);
93+
var res2 = method.invoke(null, params);
94+
95+
Assert.assertEquals(res1, res2);
96+
97+
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
98+
throw new RuntimeException(e);
99+
}
100+
}
101+
}

‎test/jdk/java/lang/reflect/code/TestTryFinally.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public static void finallyReturn(IntConsumer c) {
168168
}
169169

170170
@Test
171-
public void finallyReturn() {
171+
public void testFinallyReturn() {
172172
CoreOp.FuncOp f = getFuncOp("finallyReturn");
173173

174174
f.writeTo(System.out);

‎test/jdk/java/lang/reflect/code/bytecode/TestTryFinally.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public static void finallyReturn(IntConsumer c) {
158158
}
159159

160160
@Test
161-
public void finallyReturn() {
161+
public void testFinallyReturn() {
162162
CoreOp.FuncOp f = getFuncOp("finallyReturn");
163163

164164
MethodHandle mh = generate(f);

0 commit comments

Comments
 (0)
Please sign in to comment.