Skip to content

Commit 79aa3ad

Browse files
authored
Merge pull request #30 from Johnson0125/bugfix/static_final_field_jdk17
could change value of static final field when using jdk17 or 21
2 parents c87aba0 + 75b63e9 commit 79aa3ad

File tree

1 file changed

+20
-27
lines changed

1 file changed

+20
-27
lines changed

src/main/java/io/ebean/mocker/WithStaticFinder.java

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package io.ebean.mocker;
22

3+
import sun.misc.Unsafe;
4+
35
import java.lang.reflect.Field;
4-
import java.lang.reflect.Modifier;
5-
import java.security.AccessController;
6-
import java.security.PrivilegedAction;
76

87
/**
98
* Used to replace a "Finder" that is located as a static field (typically on an Model entity bean).
@@ -23,6 +22,14 @@ public class WithStaticFinder<T> {
2322

2423
Object testDouble;
2524

25+
Field unsafeField;
26+
27+
Unsafe unsafe;
28+
29+
Object staticFieldBase;
30+
31+
long staticFieldOffset;
32+
2633
/**
2734
* Construct with a given bean type.
2835
*/
@@ -48,25 +55,20 @@ public WithStaticFinder<T> as(Object testDouble) throws FinderFieldNotFoundExcep
4855
this.testDouble = testDouble;
4956
this.field = findField();
5057
this.field.setAccessible(true);
58+
5159
try {
52-
Field modifiersField = Field.class.getDeclaredField("modifiers");
53-
/**
54-
* If the project using this library has a SecurityManager set up, permission may be denied.
55-
* Therefor, running this as a privileged action.
56-
*/
57-
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
58-
modifiersField.setAccessible(true);
59-
return null;
60-
});
61-
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
60+
unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
61+
unsafeField.setAccessible(true);
62+
unsafe = (Unsafe) unsafeField.get(null);
63+
64+
staticFieldBase = unsafe.staticFieldBase(this.field);
65+
staticFieldOffset = unsafe.staticFieldOffset(this.field);
6266
} catch (NoSuchFieldException e) {
63-
// this fails with Java 17
6467
throw new RuntimeException("Unable to turn off final field flag for " + field, e);
6568
}
66-
6769
this.original = field.get(null);
68-
return this;
6970

71+
return this;
7072
} catch (IllegalAccessException e) {
7173
throw new RuntimeException(e);
7274
}
@@ -79,23 +81,14 @@ public WithStaticFinder<T> as(Object testDouble) throws FinderFieldNotFoundExcep
7981
* After this the test double will be used by calling code.
8082
*/
8183
public void useTestDouble() {
82-
try {
83-
this.field.set(null, testDouble);
84-
} catch (IllegalAccessException e) {
85-
throw new FinderIllegalAccessException(e);
86-
}
84+
unsafe.putObject(staticFieldBase, staticFieldOffset, testDouble);
8785
}
8886

8987
/**
9088
* Restore the original implementation using reflection.
9189
*/
9290
public void restoreOriginal() {
93-
94-
try {
95-
this.field.set(null, original);
96-
} catch (IllegalAccessException e) {
97-
throw new FinderIllegalAccessException(e);
98-
}
91+
unsafe.putObject(staticFieldBase, staticFieldOffset, original);
9992
}
10093

10194
/**

0 commit comments

Comments
 (0)