mirror of
https://github.com/EsotericSoftware/reflectasm.git
synced 2025-02-02 07:10:24 +08:00
Updated ConstructorAccess.
This commit is contained in:
parent
c599cc03ab
commit
7c3d828cc7
2
pom.xml
2
pom.xml
@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.esotericsoftware.reflectasm</groupId>
|
||||
<artifactId>reflectasm</artifactId>
|
||||
<version>1.01</version>
|
||||
<version>1.03</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>ReflectASM</name>
|
||||
<description>High performance Java reflection using code generation</description>
|
||||
|
@ -1,3 +1,3 @@
|
||||
version: 1.02
|
||||
version: 1.03
|
||||
---
|
||||
Build.build(project);
|
||||
|
@ -2,9 +2,22 @@
|
||||
package com.esotericsoftware.reflectasm;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
class AccessClassLoader extends ClassLoader {
|
||||
AccessClassLoader (ClassLoader parent) {
|
||||
static private ArrayList<AccessClassLoader> accessClassLoaders = new ArrayList();
|
||||
|
||||
static AccessClassLoader get (Class type) {
|
||||
ClassLoader parent = type.getClassLoader();
|
||||
for (int i = 0, n = accessClassLoaders.size(); i < n; i++) {
|
||||
AccessClassLoader accessClassLoader = accessClassLoaders.get(i);
|
||||
if (accessClassLoader.getParent() == parent) return accessClassLoader;
|
||||
}
|
||||
return new AccessClassLoader(parent);
|
||||
}
|
||||
|
||||
private AccessClassLoader (ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@ -12,6 +25,7 @@ class AccessClassLoader extends ClassLoader {
|
||||
// These classes come from the classloader that loaded AccessClassLoader.
|
||||
if (name.equals(FieldAccess.class.getName())) return FieldAccess.class;
|
||||
if (name.equals(MethodAccess.class.getName())) return MethodAccess.class;
|
||||
if (name.equals(ConstructorAccess.class.getName())) return ConstructorAccess.class;
|
||||
// All other classes come from the classloader that loaded the type we are accessing.
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
package com.esotericsoftware.reflectasm;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
@ -8,7 +10,16 @@ import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public abstract class ConstructorAccess<T> {
|
||||
static public <T> ConstructorAccess<T> get (Class<T> type) {
|
||||
AccessClassLoader loader = new AccessClassLoader(type.getClassLoader());
|
||||
try {
|
||||
type.getConstructor((Class[])null);
|
||||
} catch (Exception ex) {
|
||||
if (type.isMemberClass() && !Modifier.isStatic(type.getModifiers()))
|
||||
throw new RuntimeException("Class cannot be created (non-static member class): " + type.getName());
|
||||
else
|
||||
throw new RuntimeException("Class cannot be created (missing no-arg constructor): " + type.getName());
|
||||
}
|
||||
|
||||
AccessClassLoader loader = AccessClassLoader.get(type);
|
||||
|
||||
String className = type.getName();
|
||||
String accessClassName = className + "ConstructorAccess";
|
||||
@ -52,7 +63,7 @@ public abstract class ConstructorAccess<T> {
|
||||
try {
|
||||
return (ConstructorAccess)accessClass.newInstance();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Error constructing field access class: " + accessClassName, ex);
|
||||
throw new RuntimeException("Error constructing constructor access class: " + accessClassName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public abstract class FieldAccess {
|
||||
static public FieldAccess get (Class type) {
|
||||
AccessClassLoader loader = new AccessClassLoader(type.getClassLoader());
|
||||
AccessClassLoader loader = AccessClassLoader.get(type);
|
||||
|
||||
ArrayList<Field> fields = new ArrayList();
|
||||
Class nextClass = type;
|
||||
|
@ -16,7 +16,7 @@ import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public abstract class MethodAccess {
|
||||
static public MethodAccess get (Class type) {
|
||||
AccessClassLoader loader = new AccessClassLoader(type.getClassLoader());
|
||||
AccessClassLoader loader = AccessClassLoader.get(type);
|
||||
|
||||
ArrayList<Method> methods = new ArrayList();
|
||||
Class nextClass = type;
|
||||
|
@ -0,0 +1,41 @@
|
||||
|
||||
package com.esotericsoftware.reflectasm;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class ConstructorAccessTest extends TestCase {
|
||||
public void testNewInstance () {
|
||||
ConstructorAccess<SomeClass> access = ConstructorAccess.get(SomeClass.class);
|
||||
SomeClass someObject = new SomeClass();
|
||||
assertEquals(someObject, access.newInstance());
|
||||
assertEquals(someObject, access.newInstance());
|
||||
assertEquals(someObject, access.newInstance());
|
||||
}
|
||||
|
||||
static public class SomeClass {
|
||||
public String name;
|
||||
public int intValue;
|
||||
protected float test1;
|
||||
Float test2;
|
||||
private String test3;
|
||||
|
||||
public boolean equals (Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
SomeClass other = (SomeClass)obj;
|
||||
if (intValue != other.intValue) return false;
|
||||
if (name == null) {
|
||||
if (other.name != null) return false;
|
||||
} else if (!name.equals(other.name)) return false;
|
||||
if (Float.floatToIntBits(test1) != Float.floatToIntBits(other.test1)) return false;
|
||||
if (test2 == null) {
|
||||
if (other.test2 != null) return false;
|
||||
} else if (!test2.equals(other.test2)) return false;
|
||||
if (test3 == null) {
|
||||
if (other.test3 != null) return false;
|
||||
} else if (!test3.equals(other.test3)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
|
||||
package com.esotericsoftware.reflectasm.benchmark;
|
||||
|
||||
import com.esotericsoftware.reflectasm.ConstructorAccess;
|
||||
|
||||
public class ConstructorAccessBenchmark extends Benchmark {
|
||||
public ConstructorAccessBenchmark () throws Exception {
|
||||
int count = 1000000;
|
||||
Object[] dontCompileMeAway = new Object[count];
|
||||
|
||||
Class type = SomeClass.class;
|
||||
ConstructorAccess<SomeClass> access = ConstructorAccess.get(type);
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (int ii = 0; ii < count; ii++)
|
||||
dontCompileMeAway[ii] = access.newInstance();
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (int ii = 0; ii < count; ii++)
|
||||
dontCompileMeAway[ii] = type.newInstance();
|
||||
warmup = false;
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
start();
|
||||
for (int ii = 0; ii < count; ii++)
|
||||
dontCompileMeAway[ii] = access.newInstance();
|
||||
end("ConstructorAccess");
|
||||
}
|
||||
for (int i = 0; i < 100; i++) {
|
||||
start();
|
||||
for (int ii = 0; ii < count; ii++)
|
||||
dontCompileMeAway[ii] = type.newInstance();
|
||||
end("Reflection");
|
||||
}
|
||||
|
||||
chart("Constructor");
|
||||
}
|
||||
|
||||
static public class SomeClass {
|
||||
public String name;
|
||||
}
|
||||
|
||||
public static void main (String[] args) throws Exception {
|
||||
new ConstructorAccessBenchmark();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user