Skip to content

Commit 75dcc4e

Browse files
liachMandy Chung
authored and
Mandy Chung
committed
8307508: IndirectVarHandle.isAccessModeSupported throws NPE
Reviewed-by: mchung
1 parent bed9161 commit 75dcc4e

File tree

3 files changed

+78
-36
lines changed

3 files changed

+78
-36
lines changed

src/java.base/share/classes/java/lang/invoke/IndirectVarHandle.java

+13-31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -27,9 +27,7 @@
2727
package java.lang.invoke;
2828

2929
import jdk.internal.vm.annotation.ForceInline;
30-
import jdk.internal.vm.annotation.Stable;
3130

32-
import java.util.List;
3331
import java.util.function.BiFunction;
3432

3533
/**
@@ -44,8 +42,6 @@
4442
*/
4543
/* package */ final class IndirectVarHandle extends VarHandle {
4644

47-
@Stable
48-
private final MethodHandle[] handleMap = new MethodHandle[AccessMode.COUNT];
4945
private final VarHandle directTarget; // cache, for performance reasons
5046
private final VarHandle target;
5147
private final BiFunction<AccessMode, MethodHandle, MethodHandle> handleFactory;
@@ -66,16 +62,6 @@ private IndirectVarHandle(VarHandle target, Class<?> value, Class<?>[] coordinat
6662
this.coordinates = coordinates;
6763
}
6864

69-
@Override
70-
public Class<?> varType() {
71-
return value;
72-
}
73-
74-
@Override
75-
public List<Class<?>> coordinateTypes() {
76-
return List.of(coordinates);
77-
}
78-
7965
@Override
8066
MethodType accessModeTypeUncached(AccessType at) {
8167
return at.accessModeType(null, value, coordinates);
@@ -86,17 +72,20 @@ VarHandle asDirect() {
8672
return directTarget;
8773
}
8874

89-
VarHandle target() {
90-
return target;
91-
}
92-
9375
@Override
9476
public VarHandle withInvokeExactBehavior() {
9577
return hasInvokeExactBehavior()
9678
? this
9779
: new IndirectVarHandle(target, value, coordinates, handleFactory, vform, true);
9880
}
9981

82+
@Override
83+
public VarHandle withInvokeBehavior() {
84+
return !hasInvokeExactBehavior()
85+
? this
86+
: new IndirectVarHandle(target, value, coordinates, handleFactory, vform, false);
87+
}
88+
10089
@ForceInline
10190
boolean checkAccessModeThenIsDirect(VarHandle.AccessDescriptor ad) {
10291
super.checkAccessModeThenIsDirect(ad);
@@ -105,21 +94,14 @@ boolean checkAccessModeThenIsDirect(VarHandle.AccessDescriptor ad) {
10594
}
10695

10796
@Override
108-
public VarHandle withInvokeBehavior() {
109-
return !hasInvokeExactBehavior()
110-
? this
111-
: new IndirectVarHandle(target, value, coordinates, handleFactory, vform, false);
97+
public boolean isAccessModeSupported(AccessMode accessMode) {
98+
return directTarget.isAccessModeSupported(accessMode);
11299
}
113100

114101
@Override
115-
@ForceInline
116-
MethodHandle getMethodHandle(int mode) {
117-
MethodHandle handle = handleMap[mode];
118-
if (handle == null) {
119-
MethodHandle targetHandle = target.getMethodHandle(mode); // might throw UOE of access mode is not supported, which is ok
120-
handle = handleMap[mode] = handleFactory.apply(AccessMode.values()[mode], targetHandle);
121-
}
122-
return handle;
102+
MethodHandle getMethodHandleUncached(int mode) {
103+
MethodHandle targetHandle = target.getMethodHandle(mode); // might throw UOE of access mode is not supported, which is ok
104+
return handleFactory.apply(AccessMode.values()[mode], targetHandle);
123105
}
124106

125107
@Override

src/java.base/share/classes/java/lang/invoke/VarHandle.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -526,8 +526,6 @@ VarHandle asDirect() {
526526
return this;
527527
}
528528

529-
VarHandle target() { return null; }
530-
531529
/**
532530
* Returns {@code true} if this VarHandle has <a href="#invoke-exact-behavior"><em>invoke-exact behavior</em></a>.
533531
*
@@ -2120,7 +2118,7 @@ final MethodType accessModeTypeUncached(int accessTypeOrdinal) {
21202118
* @return {@code true} if the given access mode is supported, otherwise
21212119
* {@code false}.
21222120
*/
2123-
public final boolean isAccessModeSupported(AccessMode accessMode) {
2121+
public boolean isAccessModeSupported(AccessMode accessMode) {
21242122
return vform.getMemberNameOrNull(accessMode.ordinal()) != null;
21252123
}
21262124

@@ -2176,7 +2174,7 @@ public Optional<VarHandleDesc> describeConstable() {
21762174
MethodHandle[] methodHandleTable;
21772175

21782176
@ForceInline
2179-
MethodHandle getMethodHandle(int mode) {
2177+
final MethodHandle getMethodHandle(int mode) {
21802178
MethodHandle[] mhTable = methodHandleTable;
21812179
if (mhTable == null) {
21822180
mhTable = methodHandleTable = new MethodHandle[AccessMode.COUNT];
@@ -2188,7 +2186,7 @@ MethodHandle getMethodHandle(int mode) {
21882186
return mh;
21892187
}
21902188

2191-
private final MethodHandle getMethodHandleUncached(int mode) {
2189+
MethodHandle getMethodHandleUncached(int mode) {
21922190
MethodType mt = accessModeType(AccessMode.values()[mode]).
21932191
insertParameterTypes(0, VarHandle.class);
21942192
MemberName mn = vform.getMemberName(mode);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2023, 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+
/* @test
25+
* @bug 8307508
26+
* @enablePreview
27+
* @run junit IndirectVarHandleTest
28+
* @summary Test VarHandle::isAccessModeSupported on indirect VarHandle
29+
* produced by MethodHandles.filterCoordinates
30+
*/
31+
import org.junit.jupiter.api.Test;
32+
33+
import java.lang.invoke.MethodHandles;
34+
import java.lang.invoke.MethodType;
35+
import java.lang.invoke.VarHandle;
36+
import java.util.function.IntUnaryOperator;
37+
38+
import static org.junit.jupiter.api.Assertions.assertEquals;
39+
40+
public class IndirectVarHandleTest {
41+
@Test
42+
public void testIsAccessModeTypeSupported() throws Throwable {
43+
var lookup = MethodHandles.lookup();
44+
var intArrayVh = MethodHandles.arrayElementVarHandle(int[].class);
45+
var addOne = lookup.bind((IntUnaryOperator) a -> a + 1, "applyAsInt",
46+
MethodType.methodType(int.class, int.class));
47+
var offsetIntArrayVh = MethodHandles.filterCoordinates(intArrayVh, 1, addOne);
48+
49+
for (var mode : VarHandle.AccessMode.values()) {
50+
assertEquals(intArrayVh.isAccessModeSupported(mode),
51+
offsetIntArrayVh.isAccessModeSupported(mode), mode.toString());
52+
}
53+
54+
var stringArrayVh = MethodHandles.arrayElementVarHandle(String[].class);
55+
var offsetStringArrayVh = MethodHandles.filterCoordinates(stringArrayVh, 1, addOne);
56+
57+
for (var mode : VarHandle.AccessMode.values()) {
58+
assertEquals(stringArrayVh.isAccessModeSupported(mode),
59+
offsetStringArrayVh.isAccessModeSupported(mode), mode.toString());
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)