Skip to content

Commit 624fba8

Browse files
samebGuice Team
authored and
Guice Team
committed
Rework sun.misc.Unsafe usages so that we directly refer to sun.misc.Unsafe, and call getObject on it natively instead of through reflection. Calling getObject through reflection breaks Azul JVMs, because the staticFieldBase is a funny "not object", but when passed through reflection it tries to become an Object and fails.
Retrieval of the unsafe is based on how other google open source projects do it, see for example AbstractFuture: https://github.com/google/guava/blob/d4bd0c5ffa913104283e61aeb2c41bac641af042/guava/src/com/google/common/util/concurrent/AbstractFuture.java#L1340-L1365, UnsignedBytes: https://github.com/google/guava/blob/6405852bbf453b14d097b8ec3bcae494334b357d/android/guava/src/com/google/common/primitives/UnsignedBytes.java#L341-L366, and protobufs: https://github.com/protocolbuffers/protobuf/blob/520c601c99012101c816b6ccc89e8d6fc28fdbb8/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java#L289-L315 FIXES #1719 PiperOrigin-RevId: 529205332
1 parent 75df9fc commit 624fba8

File tree

4 files changed

+53
-19
lines changed

4 files changed

+53
-19
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
33
name: continuous-integration
44
env:
5-
USE_BAZEL_VERSION: '4.2.2'
5+
USE_BAZEL_VERSION: '6.1.2'
66
USE_JAVA_DISTRIBUTION: 'zulu'
77
USE_JAVA_VERSION: '11'
88

core/src/com/google/inject/internal/aop/AnonymousClassDefiner.java

+5-7
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package com.google.inject.internal.aop;
1818

19-
import java.lang.reflect.Field;
2019
import java.lang.reflect.Method;
2120

2221
/**
@@ -26,17 +25,16 @@
2625
*/
2726
final class AnonymousClassDefiner implements ClassDefiner {
2827

29-
private static final Object THE_UNSAFE;
28+
private static final sun.misc.Unsafe THE_UNSAFE;
3029
private static final Method ANONYMOUS_DEFINE_METHOD;
3130

3231
static {
3332
try {
34-
Class<?> unsafeType = Class.forName("sun.misc.Unsafe");
35-
Field theUnsafeField = unsafeType.getDeclaredField("theUnsafe");
36-
theUnsafeField.setAccessible(true);
37-
THE_UNSAFE = theUnsafeField.get(null);
33+
THE_UNSAFE = UnsafeGetter.getUnsafe();
34+
// defineAnonymousClass was removed in JDK17, so we must refer to it reflectively.
3835
ANONYMOUS_DEFINE_METHOD =
39-
unsafeType.getMethod("defineAnonymousClass", Class.class, byte[].class, Object[].class);
36+
sun.misc.Unsafe.class.getMethod(
37+
"defineAnonymousClass", Class.class, byte[].class, Object[].class);
4038
} catch (ReflectiveOperationException e) {
4139
throw new ExceptionInInitializerError(e);
4240
}

core/src/com/google/inject/internal/aop/HiddenClassDefiner.java

+7-11
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,18 @@
2828
*/
2929
final class HiddenClassDefiner implements ClassDefiner {
3030

31-
private static final Object THE_UNSAFE;
32-
private static final Object TRUSTED_LOOKUP_OFFSET;
33-
private static final Method GET_OBJECT_METHOD;
31+
private static final sun.misc.Unsafe THE_UNSAFE;
32+
private static final Object TRUSTED_LOOKUP_BASE;
33+
private static final long TRUSTED_LOOKUP_OFFSET;
3434
private static final Object HIDDEN_CLASS_OPTIONS;
3535
private static final Method HIDDEN_DEFINE_METHOD;
3636

3737
static {
3838
try {
39-
Class<?> unsafeType = Class.forName("sun.misc.Unsafe");
40-
Field theUnsafeField = unsafeType.getDeclaredField("theUnsafe");
41-
theUnsafeField.setAccessible(true);
42-
THE_UNSAFE = theUnsafeField.get(null);
39+
THE_UNSAFE = UnsafeGetter.getUnsafe();
4340
Field trustedLookupField = Lookup.class.getDeclaredField("IMPL_LOOKUP");
44-
Method offsetMethod = unsafeType.getMethod("staticFieldOffset", Field.class);
45-
TRUSTED_LOOKUP_OFFSET = offsetMethod.invoke(THE_UNSAFE, trustedLookupField);
46-
GET_OBJECT_METHOD = unsafeType.getMethod("getObject", Object.class, long.class);
41+
TRUSTED_LOOKUP_BASE = THE_UNSAFE.staticFieldBase(trustedLookupField);
42+
TRUSTED_LOOKUP_OFFSET = THE_UNSAFE.staticFieldOffset(trustedLookupField);
4743
HIDDEN_CLASS_OPTIONS = classOptions("NESTMATE");
4844
HIDDEN_DEFINE_METHOD =
4945
Lookup.class.getMethod(
@@ -56,7 +52,7 @@ final class HiddenClassDefiner implements ClassDefiner {
5652
@Override
5753
public Class<?> define(Class<?> hostClass, byte[] bytecode) throws Exception {
5854
Lookup trustedLookup =
59-
(Lookup) GET_OBJECT_METHOD.invoke(THE_UNSAFE, Lookup.class, TRUSTED_LOOKUP_OFFSET);
55+
(Lookup) THE_UNSAFE.getObject(TRUSTED_LOOKUP_BASE, TRUSTED_LOOKUP_OFFSET);
6056
Lookup definedLookup =
6157
(Lookup)
6258
HIDDEN_DEFINE_METHOD.invoke(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (C) 2023 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.inject.internal.aop;
18+
19+
final class UnsafeGetter {
20+
21+
private UnsafeGetter() {}
22+
23+
static sun.misc.Unsafe getUnsafe() throws ReflectiveOperationException {
24+
try {
25+
return sun.misc.Unsafe.getUnsafe();
26+
} catch (SecurityException unusedFallbackToReflection) {
27+
}
28+
// Note that we do not do this in a privileged action because we expect we're already in a
29+
// privileged block (from UnsafeClassDefiner).
30+
Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
31+
for (java.lang.reflect.Field f : k.getDeclaredFields()) {
32+
f.setAccessible(true);
33+
Object x = f.get(null);
34+
if (k.isInstance(x)) {
35+
return k.cast(x);
36+
}
37+
}
38+
throw new NoSuchFieldError("the Unsafe");
39+
}
40+
}

0 commit comments

Comments
 (0)