Alan Bateman 26460b6f12 8353835: Implement JEP 500: Prepare to Make Final Mean Final
Reviewed-by: liach, vlivanov, dholmes, vyazici
2025-11-18 08:06:18 +00:00

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);
}
}
}