Use byte code generation if Javassist is available.
This commit is contained in:
parent
a3b46ec9d7
commit
54d44c6ac1
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2013 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.util.internal;
|
||||
|
||||
import io.netty.logging.InternalLogger;
|
||||
import io.netty.logging.InternalLoggerFactory;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.Modifier;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
final class JavassistTypeParameterMatcherGenerator {
|
||||
|
||||
private static final InternalLogger logger =
|
||||
InternalLoggerFactory.getInstance(JavassistTypeParameterMatcherGenerator.class);
|
||||
|
||||
private static final ClassPool classPool = new ClassPool(true);
|
||||
|
||||
static TypeParameterMatcher generate(Class<?> type) {
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
if (classLoader == null) {
|
||||
classLoader = ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
return generate(type, classLoader);
|
||||
}
|
||||
|
||||
static TypeParameterMatcher generate(Class<?> type, ClassLoader classLoader) {
|
||||
final String className = "io.netty.util.internal.__matchers__." + type.getName() + "Matcher";
|
||||
try {
|
||||
try {
|
||||
return (TypeParameterMatcher) Class.forName(className, true, classLoader).newInstance();
|
||||
} catch (Exception e) {
|
||||
// Not defined in the specified class loader.
|
||||
}
|
||||
|
||||
CtClass c = classPool.getAndRename(NoOpTypeParameterMatcher.class.getName(), className);
|
||||
c.setModifiers(c.getModifiers() | Modifier.FINAL);
|
||||
c.getDeclaredMethod("match").setBody("{ return $1 instanceof " + type.getName() + "; }");
|
||||
byte[] byteCode = c.toBytecode();
|
||||
c.detach();
|
||||
Method method = ClassLoader.class.getDeclaredMethod(
|
||||
"defineClass", String.class, byte[].class, int.class, int.class);
|
||||
method.setAccessible(true);
|
||||
|
||||
Class<?> generated = (Class<?>) method.invoke(classLoader, className, byteCode, 0, byteCode.length);
|
||||
logger.debug("Generated: {}", generated.getName());
|
||||
return (TypeParameterMatcher) generated.newInstance();
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private JavassistTypeParameterMatcherGenerator() { }
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2013 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.util.internal;
|
||||
|
||||
public final class NoOpTypeParameterMatcher extends TypeParameterMatcher {
|
||||
@Override
|
||||
public boolean match(Object msg) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -48,6 +48,8 @@ public final class PlatformDependent {
|
||||
private static final boolean CAN_FREE_DIRECT_BUFFER = canFreeDirectBuffer0();
|
||||
private static final boolean IS_UNALIGNED = isUnaligned0();
|
||||
|
||||
private static final boolean HAS_JAVASSIST = hasJavassist0();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if the current platform is Android
|
||||
*/
|
||||
@ -106,6 +108,13 @@ public final class PlatformDependent {
|
||||
return IS_UNALIGNED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if and only if Javassist is available.
|
||||
*/
|
||||
public static boolean hasJavassist() {
|
||||
return HAS_JAVASSIST;
|
||||
}
|
||||
|
||||
public static long directBufferAddress(ByteBuffer buffer) {
|
||||
return PlatformDependent0.directBufferAddress(buffer);
|
||||
}
|
||||
@ -275,6 +284,15 @@ public final class PlatformDependent {
|
||||
return PlatformDependent0.isUnaligned();
|
||||
}
|
||||
|
||||
private static boolean hasJavassist0() {
|
||||
try {
|
||||
JavassistTypeParameterMatcherGenerator.generate(Object.class, PlatformDependent.class.getClassLoader());
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private PlatformDependent() {
|
||||
// only static method supported
|
||||
}
|
||||
|
@ -23,12 +23,7 @@ import java.util.Map;
|
||||
|
||||
public abstract class TypeParameterMatcher {
|
||||
|
||||
private static final TypeParameterMatcher NOOP = new TypeParameterMatcher() {
|
||||
@Override
|
||||
public boolean match(Object msg) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
private static final TypeParameterMatcher NOOP = new NoOpTypeParameterMatcher();
|
||||
|
||||
private static final ThreadLocal<Map<Class<?>, TypeParameterMatcher>> typeMap =
|
||||
new ThreadLocal<Map<Class<?>, TypeParameterMatcher>>() {
|
||||
@ -58,6 +53,13 @@ public abstract class TypeParameterMatcher {
|
||||
Class<?> messageType = (Class<?>) types[typeParamIndex];
|
||||
if (messageType == Object.class) {
|
||||
matcher = NOOP;
|
||||
} else if (PlatformDependent.hasJavassist()) {
|
||||
try {
|
||||
matcher = JavassistTypeParameterMatcherGenerator.generate(messageType);
|
||||
} catch (Exception e) {
|
||||
// Will not usually happen, but just in case.
|
||||
matcher = new ReflectiveMatcher(messageType);
|
||||
}
|
||||
} else {
|
||||
matcher = new ReflectiveMatcher(messageType);
|
||||
}
|
||||
@ -87,5 +89,5 @@ public abstract class TypeParameterMatcher {
|
||||
}
|
||||
}
|
||||
|
||||
TypeParameterMatcher() { }
|
||||
protected TypeParameterMatcher() { }
|
||||
}
|
||||
|
9
pom.xml
9
pom.xml
@ -191,6 +191,15 @@
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<!-- Byte code generator - completely optional -->
|
||||
<dependency>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
<version>3.17.1-GA</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing frameworks and related dependencies -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
|
Loading…
Reference in New Issue
Block a user