mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
357 lines
11 KiB
Java
357 lines
11 KiB
Java
/*
|
|
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
import java.lang.reflect.Method;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* Invoked by MutateFinalsTest, either directly or in a child VM, with the name of the
|
|
* test method in this class to execute.
|
|
*/
|
|
|
|
public class MutateFinals {
|
|
|
|
/**
|
|
* Usage: java MutateFinals <method-name>
|
|
*/
|
|
public static void main(String[] args) throws Exception {
|
|
invoke(args[0]);
|
|
}
|
|
|
|
/**
|
|
* Invokes the given method.
|
|
*/
|
|
static void invoke(String methodName) throws Exception {
|
|
Method m = MutateFinals.class.getDeclaredMethod(methodName);
|
|
m.invoke(null);
|
|
}
|
|
|
|
/**
|
|
* JNI SetObjectField.
|
|
*/
|
|
private static void testJniSetObjectField() throws Exception {
|
|
class C {
|
|
final Object value;
|
|
C(Object value) {
|
|
this.value = value;
|
|
}
|
|
}
|
|
Object oldValue = new Object();
|
|
Object newValue = new Object();
|
|
var obj = new C(oldValue);
|
|
jniSetObjectField(obj, newValue);
|
|
assertTrue(obj.value == newValue);
|
|
}
|
|
|
|
/**
|
|
* JNI SetBooleanField.
|
|
*/
|
|
private static void testJniSetBooleanField() throws Exception {
|
|
class C {
|
|
final boolean value;
|
|
C(boolean value) {
|
|
this.value = value;
|
|
}
|
|
}
|
|
var obj = new C(false);
|
|
jniSetBooleanField(obj, true);
|
|
assertTrue(obj.value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetByteField.
|
|
*/
|
|
private static void testJniSetByteField() throws Exception {
|
|
class C {
|
|
final byte value;
|
|
C(byte value) {
|
|
this.value = value;
|
|
}
|
|
}
|
|
byte oldValue = (byte) 1;
|
|
byte newValue = (byte) 2;
|
|
var obj = new C(oldValue);
|
|
jniSetByteField(obj, newValue);
|
|
assertEquals(newValue, obj.value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetCharField.
|
|
*/
|
|
private static void testJniSetCharField() throws Exception {
|
|
class C {
|
|
final char value;
|
|
C(char value) {
|
|
this.value = value;
|
|
}
|
|
}
|
|
char oldValue = 'A';
|
|
char newValue = 'B';
|
|
var obj = new C(oldValue);
|
|
jniSetCharField(obj, newValue);
|
|
assertEquals(newValue, obj.value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetShortField.
|
|
*/
|
|
private static void testJniSetShortField() throws Exception {
|
|
class C {
|
|
final short value;
|
|
C(short value) {
|
|
this.value = value;
|
|
}
|
|
}
|
|
short oldValue = (short) 1;
|
|
short newValue = (short) 2;
|
|
var obj = new C(oldValue);
|
|
jniSetShortField(obj, newValue);
|
|
assertEquals(newValue, obj.value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetIntField.
|
|
*/
|
|
private static void testJniSetIntField() throws Exception {
|
|
class C {
|
|
final int value;
|
|
C(int value) {
|
|
this.value = value;
|
|
}
|
|
}
|
|
int oldValue = 1;
|
|
int newValue = 2;
|
|
var obj = new C(oldValue);
|
|
jniSetIntField(obj, newValue);
|
|
assertEquals(newValue, obj.value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetLongField.
|
|
*/
|
|
private static void testJniSetLongField() throws Exception {
|
|
class C {
|
|
final long value;
|
|
C(long value) {
|
|
this.value = value;
|
|
}
|
|
}
|
|
long oldValue = 1L;
|
|
long newValue = 2L;
|
|
var obj = new C(oldValue);
|
|
jniSetLongField(obj, newValue);
|
|
assertEquals(newValue, obj.value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetFloatField.
|
|
*/
|
|
private static void testJniSetFloatField() throws Exception {
|
|
class C {
|
|
final float value;
|
|
C(float value) {
|
|
this.value = value;
|
|
}
|
|
}
|
|
float oldValue = 1.0f;
|
|
float newValue = 2.0f;
|
|
var obj = new C(oldValue);
|
|
jniSetFloatField(obj, newValue);
|
|
assertEquals(newValue, obj.value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetDoubleField.
|
|
*/
|
|
private static void testJniSetDoubleField() throws Exception {
|
|
class C {
|
|
final double value;
|
|
C(double value) {
|
|
this.value = value;
|
|
}
|
|
}
|
|
double oldValue = 1.0d;
|
|
double newValue = 2.0d;
|
|
var obj = new C(oldValue);
|
|
jniSetDoubleField(obj, newValue);
|
|
assertEquals(newValue, obj.value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetStaticObjectField.
|
|
*/
|
|
private static void testJniSetStaticObjectField() throws Exception {
|
|
class C {
|
|
static final Object value = new Object();
|
|
}
|
|
Object newValue = new Object();
|
|
jniSetStaticObjectField(C.class, newValue);
|
|
assertTrue(C.value == newValue);
|
|
}
|
|
|
|
/**
|
|
* JNI SetStaticBooleanField.
|
|
*/
|
|
private static void testJniSetStaticBooleanField() throws Exception {
|
|
class C {
|
|
static final boolean value = false;
|
|
}
|
|
jniSetStaticBooleanField(C.class, true);
|
|
// use reflection as field treated as constant by compiler
|
|
boolean value = (boolean) C.class.getDeclaredField("value").get(null);
|
|
assertTrue(value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetStaticByteField.
|
|
*/
|
|
private static void testJniSetStaticByteField() throws Exception {
|
|
class C {
|
|
static final byte value = (byte) 1;
|
|
}
|
|
byte newValue = (byte) 2;
|
|
jniSetStaticByteField(C.class, newValue);
|
|
// use reflection as field treated as constant by compiler
|
|
byte value = (byte) C.class.getDeclaredField("value").get(null);
|
|
assertEquals(newValue, value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetStaticCharField.
|
|
*/
|
|
private static void testJniSetStaticCharField() throws Exception {
|
|
class C {
|
|
static final char value = 'A';
|
|
}
|
|
char newValue = 'B';
|
|
jniSetStaticCharField(C.class, newValue);
|
|
// use reflection as field treated as constant by compiler
|
|
char value = (char) C.class.getDeclaredField("value").get(null);
|
|
assertEquals(newValue, value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetStaticShortField.
|
|
*/
|
|
private static void testJniSetStaticShortField() throws Exception {
|
|
class C {
|
|
static final short value = (short) 1;
|
|
}
|
|
short newValue = (short) 2;
|
|
jniSetStaticShortField(C.class, newValue);
|
|
// use reflection as field treated as constant by compiler
|
|
short value = (short) C.class.getDeclaredField("value").get(null);
|
|
assertEquals(newValue, value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetStaticIntField.
|
|
*/
|
|
private static void testJniSetStaticIntField() throws Exception {
|
|
class C {
|
|
static final int value = 1;
|
|
}
|
|
int newValue = 2;
|
|
jniSetStaticIntField(C.class, newValue);
|
|
// use reflection as field treated as constant by compiler
|
|
int value = (int) C.class.getDeclaredField("value").get(null);
|
|
assertEquals(newValue, value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetStaticLongField.
|
|
*/
|
|
private static void testJniSetStaticLongField() throws Exception {
|
|
class C {
|
|
static final long value = 1L;
|
|
}
|
|
long newValue = 2L;
|
|
jniSetStaticLongField(C.class, newValue);
|
|
// use reflection as field treated as constant by compiler
|
|
long value = (long) C.class.getDeclaredField("value").get(null);
|
|
assertEquals(newValue, value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetStaticFloatField.
|
|
*/
|
|
private static void testJniSetStaticFloatField() throws Exception {
|
|
class C {
|
|
static final float value = 1.0f;
|
|
}
|
|
float newValue = 2.0f;
|
|
jniSetStaticFloatField(C.class, newValue);
|
|
// use reflection as field treated as constant by compiler
|
|
float value = (float) C.class.getDeclaredField("value").get(null);
|
|
assertEquals(newValue, value);
|
|
}
|
|
|
|
/**
|
|
* JNI SetStaticDoubleField.
|
|
*/
|
|
private static void testJniSetStaticDoubleField() throws Exception {
|
|
class C {
|
|
static final double value = 1.0d;
|
|
}
|
|
double newValue = 2.0f;
|
|
jniSetStaticDoubleField(C.class, newValue);
|
|
// use reflection as field treated as constant by compiler
|
|
double value = (double) C.class.getDeclaredField("value").get(null);
|
|
assertEquals(newValue, value);
|
|
}
|
|
|
|
private static native void jniSetObjectField(Object obj, Object value);
|
|
private static native void jniSetBooleanField(Object obj, boolean value);
|
|
private static native void jniSetByteField(Object obj, byte value);
|
|
private static native void jniSetCharField(Object obj, char value);
|
|
private static native void jniSetShortField(Object obj, short value);
|
|
private static native void jniSetIntField(Object obj, int value);
|
|
private static native void jniSetLongField(Object obj, long value);
|
|
private static native void jniSetFloatField(Object obj, float value);
|
|
private static native void jniSetDoubleField(Object obj, double value);
|
|
|
|
private static native void jniSetStaticObjectField(Class<?> clazz, Object value);
|
|
private static native void jniSetStaticBooleanField(Class<?> clazz, boolean value);
|
|
private static native void jniSetStaticByteField(Class<?> clazz, byte value);
|
|
private static native void jniSetStaticCharField(Class<?> clazz, char value);
|
|
private static native void jniSetStaticShortField(Class<?> clazz, short value);
|
|
private static native void jniSetStaticIntField(Class<?> clazz, int value);
|
|
private static native void jniSetStaticLongField(Class<?> clazz, long value);
|
|
private static native void jniSetStaticFloatField(Class<?> clazz, float value);
|
|
private static native void jniSetStaticDoubleField(Class<?> clazz, double value);
|
|
|
|
static {
|
|
System.loadLibrary("MutateFinals");
|
|
}
|
|
|
|
private static void assertTrue(boolean e) {
|
|
if (!e) throw new RuntimeException("Not true as expected");
|
|
}
|
|
|
|
private static void assertEquals(Object expected, Object actual) {
|
|
if (!Objects.equals(expected, actual)) {
|
|
throw new RuntimeException("Actual: " + actual + ", expected: " + expected);
|
|
}
|
|
}
|
|
}
|