Skip to content

Commit e3333f1

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

File tree

2 files changed

+199
-10
lines changed

2 files changed

+199
-10
lines changed

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

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,26 @@
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;
2838
import org.junit.jupiter.api.Test;
39+
import sun.misc.Unsafe;
2940

3041
import static org.awaitility.Awaitility.await;
3142

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

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)