Skip to content

Commit 9a3e96c

Browse files
committed
Change jdk9-compile profile maven configuration from release to maven.compiler.target
1 parent 0286216 commit 9a3e96c

File tree

2 files changed

+192
-10
lines changed

2 files changed

+192
-10
lines changed

dubbo-common/src/test/java/org/apache/dubbo/common/timer/HashedWheelTimerTest.java

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,27 @@
1717
package org.apache.dubbo.common.timer;
1818

1919
import org.apache.dubbo.common.utils.NamedThreadFactory;
20+
import org.apache.dubbo.common.utils.SystemPropertyConfigUtils;
2021

2122
import java.lang.ref.WeakReference;
23+
import java.lang.reflect.AccessibleObject;
24+
import java.lang.reflect.Array;
25+
import java.lang.reflect.Field;
26+
import java.lang.reflect.GenericArrayType;
27+
import java.lang.reflect.ParameterizedType;
28+
import java.lang.reflect.Type;
29+
import java.lang.reflect.TypeVariable;
30+
import java.security.AccessController;
31+
import java.security.PrivilegedAction;
2232
import java.util.LinkedList;
2333
import java.util.List;
2434
import java.util.concurrent.CountDownLatch;
2535
import java.util.concurrent.TimeUnit;
2636

2737
import org.junit.jupiter.api.Assertions;
38+
import org.junit.jupiter.api.DisplayName;
2839
import org.junit.jupiter.api.Test;
40+
import sun.misc.Unsafe;
2941

3042
import static org.awaitility.Awaitility.await;
3143

@@ -171,4 +183,181 @@ void stopTaskTest() throws InterruptedException {
171183
// this will throw an exception
172184
Assertions.assertThrows(RuntimeException.class, () -> timer.newTimeout(new EmptyTask(), 5, TimeUnit.SECONDS));
173185
}
186+
187+
@Test
188+
@DisplayName("Check whether sun.misc.Unsafe (used by latest Netty HashedWheelTimer) could be compiled or not.")
189+
void unsafeTest() {
190+
// attempt to access field Unsafe#theUnsafe
191+
final Object maybeUnsafe = AccessController.doPrivileged(new PrivilegedAction<Object>() {
192+
@Override
193+
public Object run() {
194+
try {
195+
final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
196+
// We always want to try using Unsafe as the access still works on java9 as well and
197+
// we need it for out native-transports and many optimizations.
198+
Throwable cause = ReflectionUtil.trySetAccessible(unsafeField, false);
199+
if (cause != null) {
200+
return cause;
201+
}
202+
// the unsafe instance
203+
return unsafeField.get(null);
204+
} catch (NoSuchFieldException | IllegalAccessException | SecurityException e) {
205+
return e;
206+
} catch (NoClassDefFoundError e) {
207+
// Also catch NoClassDefFoundError in case someone uses for example OSGI and it made
208+
// Unsafe unloadable.
209+
return e;
210+
}
211+
}
212+
});
213+
214+
Assertions.assertInstanceOf(Unsafe.class, maybeUnsafe);
215+
}
216+
217+
private static final class ReflectionUtil {
218+
219+
private ReflectionUtil() {}
220+
221+
/**
222+
* Try to call {@link AccessibleObject#setAccessible(boolean)} but will catch any {@link SecurityException} and
223+
* {@link java.lang.reflect.InaccessibleObjectException} and return it.
224+
* The caller must check if it returns {@code null} and if not handle the returned exception.
225+
*/
226+
public static Throwable trySetAccessible(AccessibleObject object, boolean checkAccessible) {
227+
if (checkAccessible && !explicitTryReflectionSetAccessible0()) {
228+
return new UnsupportedOperationException("Reflective setAccessible(true) disabled");
229+
}
230+
try {
231+
object.setAccessible(true);
232+
return null;
233+
} catch (SecurityException e) {
234+
return e;
235+
} catch (RuntimeException e) {
236+
return handleInaccessibleObjectException(e);
237+
}
238+
}
239+
240+
private static RuntimeException handleInaccessibleObjectException(RuntimeException e) {
241+
// JDK 9 can throw an inaccessible object exception here; since Netty compiles
242+
// against JDK 7 and this exception was only added in JDK 9, we have to weakly
243+
// check the type
244+
if ("java.lang.reflect.InaccessibleObjectException"
245+
.equals(e.getClass().getName())) {
246+
return e;
247+
}
248+
throw e;
249+
}
250+
251+
private static Class<?> fail(Class<?> type, String typeParamName) {
252+
throw new IllegalStateException(
253+
"cannot determine the type of the type parameter '" + typeParamName + "': " + type);
254+
}
255+
256+
/**
257+
* Resolve a type parameter of a class that is a subclass of the given parametrized superclass.
258+
*
259+
* @param object The object to resolve the type parameter for
260+
* @param parametrizedSuperclass The parametrized superclass
261+
* @param typeParamName The name of the type parameter to resolve
262+
* @return The resolved type parameter
263+
* @throws IllegalStateException if the type parameter could not be resolved
264+
*/
265+
public static Class<?> resolveTypeParameter(
266+
final Object object, Class<?> parametrizedSuperclass, String typeParamName) {
267+
final Class<?> thisClass = object.getClass();
268+
Class<?> currentClass = thisClass;
269+
for (; ; ) {
270+
if (currentClass.getSuperclass() == parametrizedSuperclass) {
271+
int typeParamIndex = -1;
272+
TypeVariable<?>[] typeParams = currentClass.getSuperclass().getTypeParameters();
273+
for (int i = 0; i < typeParams.length; i++) {
274+
if (typeParamName.equals(typeParams[i].getName())) {
275+
typeParamIndex = i;
276+
break;
277+
}
278+
}
279+
280+
if (typeParamIndex < 0) {
281+
throw new IllegalStateException(
282+
"unknown type parameter '" + typeParamName + "': " + parametrizedSuperclass);
283+
}
284+
285+
Type genericSuperType = currentClass.getGenericSuperclass();
286+
if (!(genericSuperType instanceof ParameterizedType)) {
287+
return Object.class;
288+
}
289+
290+
Type[] actualTypeParams = ((ParameterizedType) genericSuperType).getActualTypeArguments();
291+
292+
Type actualTypeParam = actualTypeParams[typeParamIndex];
293+
if (actualTypeParam instanceof ParameterizedType) {
294+
actualTypeParam = ((ParameterizedType) actualTypeParam).getRawType();
295+
}
296+
if (actualTypeParam instanceof Class) {
297+
return (Class<?>) actualTypeParam;
298+
}
299+
if (actualTypeParam instanceof GenericArrayType) {
300+
Type componentType = ((GenericArrayType) actualTypeParam).getGenericComponentType();
301+
if (componentType instanceof ParameterizedType) {
302+
componentType = ((ParameterizedType) componentType).getRawType();
303+
}
304+
if (componentType instanceof Class) {
305+
return Array.newInstance((Class<?>) componentType, 0)
306+
.getClass();
307+
}
308+
}
309+
if (actualTypeParam instanceof TypeVariable) {
310+
// Resolved type parameter points to another type parameter.
311+
TypeVariable<?> v = (TypeVariable<?>) actualTypeParam;
312+
if (!(v.getGenericDeclaration() instanceof Class)) {
313+
return Object.class;
314+
}
315+
316+
currentClass = thisClass;
317+
parametrizedSuperclass = (Class<?>) v.getGenericDeclaration();
318+
typeParamName = v.getName();
319+
if (parametrizedSuperclass.isAssignableFrom(thisClass)) {
320+
continue;
321+
}
322+
return Object.class;
323+
}
324+
325+
return fail(thisClass, typeParamName);
326+
}
327+
currentClass = currentClass.getSuperclass();
328+
if (currentClass == null) {
329+
return fail(thisClass, typeParamName);
330+
}
331+
}
332+
}
333+
334+
private static boolean explicitTryReflectionSetAccessible0() {
335+
// we disable reflective access
336+
return Boolean.parseBoolean(SystemPropertyConfigUtils.getSystemProperty(
337+
"io.netty.tryReflectionSetAccessible",
338+
String.valueOf(javaVersion() < 9 || RUNNING_IN_NATIVE_IMAGE)));
339+
}
340+
341+
private static final boolean RUNNING_IN_NATIVE_IMAGE =
342+
SystemPropertyConfigUtils.getSystemProperty("org.graalvm.nativeimage.imagecode") != null;
343+
344+
private static int javaVersion() {
345+
return majorVersion(SystemPropertyConfigUtils.getSystemProperty("java.specification.version", "1.6"));
346+
}
347+
348+
private static int majorVersion(final String javaSpecVersion) {
349+
final String[] components = javaSpecVersion.split("\\.");
350+
final int[] version = new int[components.length];
351+
for (int i = 0; i < components.length; i++) {
352+
version[i] = Integer.parseInt(components[i]);
353+
}
354+
355+
if (version[0] == 1) {
356+
assert version[1] >= 6;
357+
return version[1];
358+
} else {
359+
return version[0];
360+
}
361+
}
362+
}
174363
}

pom.xml

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -815,16 +815,9 @@
815815
<activation>
816816
<jdk>[1.9,)</jdk>
817817
</activation>
818-
<build>
819-
<plugins>
820-
<plugin>
821-
<artifactId>maven-compiler-plugin</artifactId>
822-
<configuration>
823-
<release>8</release>
824-
</configuration>
825-
</plugin>
826-
</plugins>
827-
</build>
818+
<properties>
819+
<maven.compiler.target>1.8</maven.compiler.target>
820+
</properties>
828821
</profile>
829822

830823
<profile>

0 commit comments

Comments
 (0)