Skip to content

Commit

Permalink
workaround for different treatment of default methods for java 8 and …
Browse files Browse the repository at this point in the history
…java 11
  • Loading branch information
kaifox committed May 7, 2020
1 parent 9e9f614 commit ef9e430
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package org.tensorics.core.tensorbacked;

import org.tensorics.core.tensor.Tensor;
import org.tensorics.core.util.JavaVersions;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static java.util.Objects.requireNonNull;

Expand All @@ -22,7 +21,7 @@ public static <V, T extends Tensorbacked<V>> T create(Class<T> tensorbackedType,
throw new IllegalArgumentException("The given tensorbacked type '" + tensorbackedType
+ "' is not an interface! Therefore, it cannot be instantiated by proxying!");
}
return (T) Proxy.newProxyInstance(Tensorbacked.class.getClassLoader(), new Class<?>[] { tensorbackedType },
return (T) Proxy.newProxyInstance(Tensorbacked.class.getClassLoader(), new Class<?>[]{tensorbackedType},
new DelegatingInvocationHandler<>(tensor, tensorbackedType));
}

Expand All @@ -39,11 +38,8 @@ public DelegatingInvocationHandler(Tensor<V> delegate, Class<T> intfc) {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if (method.isDefault()) {
return MethodHandles.lookup()
.findSpecial(intfc, method.getName(),
MethodType.methodType(method.getReturnType(), method.getParameterTypes()), intfc)
.bindTo(proxy).invokeWithArguments(args);

MethodCallHandler callHandler = callHandlerFor(intfc, method);
return callHandler.invoke(proxy, args);
}

if (Tensorbacked.class.equals(method.getDeclaringClass()) && "tensor".equals(method.getName())
Expand All @@ -60,35 +56,29 @@ private interface MethodCallHandler {
Object invoke(Object proxy, Object[] args) throws Throwable;
}

@FunctionalInterface
private interface MethodInterpreter extends InvocationHandler {

@Override
default Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodCallHandler handler = interpret(method);
return handler.invoke(proxy, args);
}

MethodCallHandler interpret(Method method);
private static MethodCallHandler callHandlerFor(Class<?> intfc, Method method) {
MethodHandle handle = getMethodHandle(intfc, method);
return (proxy, args) -> handle.bindTo(proxy).invokeWithArguments(args);
}

private static class DefaultMethodCallHandler {

private DefaultMethodCallHandler() {
}

private static final ConcurrentMap<Method, MethodCallHandler> cache = new ConcurrentHashMap<>();

private static MethodCallHandler forMethod(Method method) {
return cache.computeIfAbsent(method, m -> {
MethodHandle handle = getMethodHandle(m);
return (proxy, args) -> handle.bindTo(proxy).invokeWithArguments(args);
});
}

private static MethodHandle getMethodHandle(Method method) {
Class<?> declaringClass = method.getDeclaringClass();
private static MethodHandle getMethodHandle(Class<?> intfc, Method method) {
Class<?> declaringClass = method.getDeclaringClass();

/*
XXX: This is not too nice: For some reason, the original code (java) 8 did not run in java 11 anymore.
And vice versa ... what the exact border is where it stopped working was not full checked.
So potentially more research would be needed here.
*/
if (JavaVersions.isAtLeastJava11()) {
try {
return MethodHandles.lookup()
.findSpecial(intfc, method.getName(),
MethodType.methodType(method.getReturnType(), method.getParameterTypes()), intfc);
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new RuntimeException(e);
}
} else {
try {
Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class
.getDeclaredConstructor(Class.class, int.class);
Expand Down
20 changes: 20 additions & 0 deletions src/java/org/tensorics/core/util/JavaVersions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.tensorics.core.util;

/**
* Contains utility methods related to java versions
*/
public final class JavaVersions {

private JavaVersions() {
throw new UnsupportedOperationException("only static methods");
}

/**
* Determines if the actual running jvm is at least java 11
*
* @return true if it is java 11 or higher, false otherwise
*/
public static boolean isAtLeastJava11() {
return "11".compareTo(System.getProperty("java.version")) <= 0;
}
}
16 changes: 16 additions & 0 deletions src/test/org/tensorics/core/util/JavaVersionsTries.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.tensorics.core.util;

import org.junit.Test;

public class JavaVersionsTries {

@Test
public void testJavaVersion() {
System.out.println(System.getProperty("java.version"));
System.out.println("11".compareTo("1.8") <= 0);
System.out.println("11".compareTo("11") <= 0);
System.out.println("11".compareTo("12") <= 0);
System.out.println(JavaVersions.isAtLeastJava11());
}

}

0 comments on commit ef9e430

Please sign in to comment.