下面列出了怎么用java.lang.invoke.VarHandle的API类实例代码及写法,或者点击链接到github查看源代码。
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessShort recv, VarHandle vh) {
checkUOE(() -> {
vh.set(recv, (short)0x4567);
});
checkUOE(() -> {
vh.setVolatile(recv, (short)0x4567);
});
checkUOE(() -> {
vh.setRelease(recv, (short)0x4567);
});
checkUOE(() -> {
vh.setOpaque(recv, (short)0x4567);
});
}
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessLong recv, VarHandle vh) {
checkUOE(() -> {
vh.set(recv, 0xCAFEBABECAFEBABEL);
});
checkUOE(() -> {
vh.setVolatile(recv, 0xCAFEBABECAFEBABEL);
});
checkUOE(() -> {
vh.setRelease(recv, 0xCAFEBABECAFEBABEL);
});
checkUOE(() -> {
vh.setOpaque(recv, 0xCAFEBABECAFEBABEL);
});
}
static void testStaticFinalFieldUnsupported(VarHandle vh) {
checkUOE(() -> {
vh.set(0xCAFEBABECAFEBABEL);
});
checkUOE(() -> {
vh.setVolatile(0xCAFEBABECAFEBABEL);
});
checkUOE(() -> {
vh.setRelease(0xCAFEBABECAFEBABEL);
});
checkUOE(() -> {
vh.setOpaque(0xCAFEBABECAFEBABEL);
});
}
/**
* Pushes a task. Call only by owner in unshared queues.
*
* @param task the task. Caller must ensure non-null.
* @throws RejectedExecutionException if array cannot be resized
*/
final void push(ForkJoinTask<?> task) {
ForkJoinTask<?>[] a;
int s = top, d = s - base, cap, m;
ForkJoinPool p = pool;
if ((a = array) != null && (cap = a.length) > 0) {
QA.setRelease(a, (m = cap - 1) & s, task);
top = s + 1;
if (d == m)
growArray(false);
else if (QA.getAcquire(a, m & (s - 1)) == null && p != null) {
VarHandle.fullFence(); // was empty
p.signalWork(null);
}
}
}
static void testStaticFinalFieldUnsupported(VarHandle vh) {
checkUOE(() -> {
vh.set('\u4567');
});
checkUOE(() -> {
vh.setVolatile('\u4567');
});
checkUOE(() -> {
vh.setRelease('\u4567');
});
checkUOE(() -> {
vh.setOpaque('\u4567');
});
}
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) {
checkUOE(() -> {
vh.set(recv, '\u4567');
});
checkUOE(() -> {
vh.setVolatile(recv, '\u4567');
});
checkUOE(() -> {
vh.setRelease(recv, '\u4567');
});
checkUOE(() -> {
vh.setOpaque(recv, '\u4567');
});
}
/**
* Pushes a task. Call only by owner in unshared queues.
*
* @param task the task. Caller must ensure non-null.
* @throws RejectedExecutionException if array cannot be resized
*/
final void push(ForkJoinTask<?> task) {
int s = top; ForkJoinTask<?>[] a; int al, d;
if ((a = array) != null && (al = a.length) > 0) {
int index = (al - 1) & s;
ForkJoinPool p = pool;
top = s + 1;
QA.setRelease(a, index, task);
if ((d = base - s) == 0 && p != null) {
VarHandle.fullFence();
p.signalWork();
}
else if (d + al == 1)
growArray();
}
}
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessInt recv, VarHandle vh) {
checkUOE(() -> {
vh.set(recv, 0x89ABCDEF);
});
checkUOE(() -> {
vh.setVolatile(recv, 0x89ABCDEF);
});
checkUOE(() -> {
vh.setRelease(recv, 0x89ABCDEF);
});
checkUOE(() -> {
vh.setOpaque(recv, 0x89ABCDEF);
});
}
static void testStaticFinalFieldUnsupported(VarHandle vh) {
checkUOE(() -> {
vh.set(0x89ABCDEF);
});
checkUOE(() -> {
vh.setVolatile(0x89ABCDEF);
});
checkUOE(() -> {
vh.setRelease(0x89ABCDEF);
});
checkUOE(() -> {
vh.setOpaque(0x89ABCDEF);
});
}
@Override
public void start(long gen, String taskName, long nanoTime) {
long localIdx = (long) IDX.get(this);
int i = (int) (localIdx & maxEventsMax);
STRINGS.setOpaque(taskNames, i, taskName);
LONGS.setOpaque(nanoTimes, i, nanoTime);
LONGS.setOpaque(genOps, i, gen + START_OP);
IDX.setRelease(this, localIdx + 1);
VarHandle.storeStoreFence();
}
@Override
public void start(long gen, String taskName, String subTaskName, long nanoTime) {
long localIdx = (long) IDX.get(this);
int i = (int) (localIdx & maxEventsMax);
STRINGS.setOpaque(taskNames, i, taskName);
STRINGS.setOpaque(tagNames, i, subTaskName);
LONGS.setOpaque(nanoTimes, i, nanoTime);
LONGS.setOpaque(genOps, i, gen + START_S_OP);
IDX.setRelease(this, localIdx + 1);
VarHandle.storeStoreFence();
}
@Override
public void link(long gen, long linkId) {
long localIdx = (long) IDX.get(this);
int i = (int) (localIdx & maxEventsMax);
LONGS.setOpaque(tagIds, i, linkId);
LONGS.setOpaque(genOps, i, gen + LINK_OP);
IDX.setRelease(this, localIdx + 1);
VarHandle.storeStoreFence();
}
@Override
public void stop(long gen, String taskName, long nanoTime) {
long localIdx = (long) IDX.get(this);
int i = (int) (localIdx & maxEventsMax);
STRINGS.setOpaque(taskNames, i, taskName);
LONGS.setOpaque(nanoTimes, i, nanoTime);
LONGS.setOpaque(genOps, i, gen + STOP_OP);
IDX.setRelease(this, localIdx + 1);
VarHandle.storeStoreFence();
}
@Override
public void stop(long gen, String taskName, String subTaskName, long nanoTime) {
long localIdx = (long) IDX.get(this);
int i = (int) (localIdx & maxEventsMax);
STRINGS.setOpaque(taskNames, i, taskName);
STRINGS.setOpaque(tagNames, i, subTaskName);
LONGS.setOpaque(nanoTimes, i, nanoTime);
LONGS.setOpaque(genOps, i, gen + STOP_S_OP);
IDX.setRelease(this, localIdx + 1);
VarHandle.storeStoreFence();
}
@Override
public void event(long gen, String eventName, long nanoTime) {
long localIdx = (long) IDX.get(this);
int i = (int) (localIdx & maxEventsMax);
STRINGS.setOpaque(taskNames, i, eventName);
LONGS.setOpaque(nanoTimes, i, nanoTime);
LONGS.setOpaque(genOps, i, gen + EVENT_OP);
IDX.setRelease(this, localIdx + 1);
VarHandle.storeStoreFence();
}
@DataProvider
public Object[][] varHandlesProvider() throws Exception {
List<VarHandle> vhs = new ArrayList<>();
vhs.add(vhField);
vhs.add(vhStaticField);
vhs.add(vhArray);
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
}
@Override
public void attachTag(long gen, String tagName, long tagId) {
long localIdx = (long) IDX.get(this);
int i = (int) (localIdx & maxEventsMax);
STRINGS.setOpaque(tagNames, i, tagName);
LONGS.setOpaque(tagIds, i, tagId);
LONGS.setOpaque(genOps, i, gen + ATTACH_T_OP);
IDX.setRelease(this, localIdx + 1);
VarHandle.storeStoreFence();
}
@Override
public void attachKeyedTag(long gen, String name, long value0, long value1) {
long localIdx = (long) IDX.get(this);
int i = (int) (localIdx & maxEventsMax);
STRINGS.setOpaque(tagNames, i, name);
LONGS.setOpaque(tagIds, i, value0);
LONGS.setOpaque(nanoTimes, i, value1);
LONGS.setOpaque(genOps, i, gen + ATTACH_SNN_OP);
IDX.setRelease(this, localIdx + 1);
VarHandle.storeStoreFence();
}
@Override
public void resetForTest() {
Arrays.fill(taskNames, null);
Arrays.fill(markers, null);
Arrays.fill(tagNames, null);
Arrays.fill(tagIds, 0);
Arrays.fill(nanoTimes, 0);
Arrays.fill(genOps, 0);
IDX.setRelease(this, 0L);
VarHandle.storeStoreFence();
}
@Test(dataProvider = "typesProvider")
public void testTypes(VarHandle vh, List<Class<?>> pts) {
assertEquals(vh.varType(), long.class);
assertEquals(vh.coordinateTypes(), pts);
testTypes(vh);
}
@Test(dataProvider = "typesProvider")
public void testTypes(VarHandle vh, List<Class<?>> pts) {
assertEquals(vh.varType(), char.class);
assertEquals(vh.coordinateTypes(), pts);
testTypes(vh);
}
@Test
@Tag("PASSING")
@Order(4)
public void getPrivateVariableFromConstructedClassViaVarHandles() {
try {
/*
* DONE:
* Replace the "null"s with valid values to get a VarHandle.
* Check API: java.lang.invoke.MethodHandles.privateLookupIn(?, ?)
* HINT: params are Target class and type of lookup
* Check API: java.lang.invoke.MethodHandles.Lookup.findVarHandle(?, ?, ?)
* HINT: params are Declaring class, Variable name, Variable type
*/
VarHandle privateVariableVarHandle = MethodHandles
.privateLookupIn(TestSolutionGetter.class, MethodHandles.lookup())
.findVarHandle(TestSolutionGetter.class, "privateVariable", Integer.class);
assertEquals(1,
privateVariableVarHandle.coordinateTypes().size(),
"There should only be one coordinateType");
assertEquals(TestSolutionGetter.class,
privateVariableVarHandle.coordinateTypes().get(0),
"The only coordinate type is AttributeGetterTest");
assertTrue(privateVariableVarHandle.isAccessModeSupported(VarHandle.AccessMode.GET),
"Access mode for a GET should be true");
assertEquals(2,
privateVariableVarHandle.get(this),
"The value of the field should be 2");
} catch (NoSuchFieldException | IllegalAccessException | NullPointerException e) {
fail(TEST_FAILURE.getValue() + e.getMessage());
}
}
@Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
public void reflectAsFromFindVirtual(VarHandle.AccessMode accessMode) throws Exception {
VarHandle v = handle();
MethodHandle mh = MethodHandles.publicLookup().findVirtual(
VarHandle.class, accessMode.methodName(), v.accessModeType(accessMode));
MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
info.reflectAs(Method.class, MethodHandles.lookup());
}
@Test(dataProvider = "typesProvider")
public void testTypes(VarHandle vh, List<Class<?>> pts) {
assertEquals(vh.varType(), float.class);
assertEquals(vh.coordinateTypes(), pts);
testTypes(vh);
}
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandleSource vhs) {
VarHandle vh = vhs.s;
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
}
@Test(dataProvider = "varHandlesProvider")
public void testIsAccessModeSupported(VarHandleSource vhs) {
VarHandle vh = vhs.s;
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
}
@Test
@Tag("TODO")
@Order(4)
public void getPrivateVariableFromConstructedClassViaVarHandles() {
try {
/*
* TODO:
* Replace the "null"s with valid values to get a VarHandle.
* Check API: java.lang.invoke.MethodHandles.privateLookupIn(?, ?)
* HINT: params are Target class and type of lookup
* Check API: java.lang.invoke.MethodHandles.Lookup.findVarHandle(?, ?, ?)
* HINT: params are Declaring class, Variable name, Variable type
*/
VarHandle privateVariableVarHandle = MethodHandles
.privateLookupIn(null, MethodHandles.lookup())
.findVarHandle(null, null, null);
assertEquals(1,
privateVariableVarHandle.coordinateTypes().size(),
"There should only be one coordinateType");
assertEquals(TestKataGetter.class,
privateVariableVarHandle.coordinateTypes().get(0),
"The only coordinate type is AttributeGetterTest");
assertTrue(privateVariableVarHandle.isAccessModeSupported(VarHandle.AccessMode.GET),
"Access mode for a GET should be true");
assertEquals(2,
privateVariableVarHandle.get(this),
"The value of the field should be 2");
} catch (NoSuchFieldException | IllegalAccessException | NullPointerException e) {
fail(TEST_FAILURE.getValue() + e.getMessage());
}
}
@Test(dataProvider = "typesProvider")
public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
assertEquals(vh.varType(), float.class);
assertEquals(vh.coordinateTypes(), pts);
testTypes(vh);
}
/**
* Tries to expand buffer and add item, returning true on
* success. Currently fails only if out of memory.
*/
final boolean growAndOffer(T item, Object[] a, int t) {
int cap = 0, newCap = 0;
Object[] newArray = null;
if (a != null && (cap = a.length) > 0 && (newCap = cap << 1) > 0) {
try {
newArray = new Object[newCap];
} catch (OutOfMemoryError ex) {
}
}
if (newArray == null)
return false;
else { // take and move items
int newMask = newCap - 1;
newArray[t-- & newMask] = item;
for (int mask = cap - 1, k = mask; k >= 0; --k) {
Object x = QA.getAndSet(a, t & mask, null);
if (x == null)
break; // already consumed
else
newArray[t-- & newMask] = x;
}
array = newArray;
VarHandle.releaseFence(); // release array and slots
return true;
}
}
@Test(dataProvider = "accessModesProvider", expectedExceptions = UnsupportedOperationException.class)
public void methodHandleInvoke(VarHandle.AccessMode accessMode) throws Throwable {
VarHandle v = handle();
// Try a reflective invoke using a MethodHandle
MethodHandle mh = MethodHandles.lookup().unreflect(
VarHandle.class.getMethod(accessMode.methodName(), Object[].class));
// Use invoke to avoid WrongMethodTypeException for
// non-signature-polymorphic return types
Object o = (Object) mh.invoke(v, new Object[]{});
}