mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2024-11-27 05:05:24 +01:00
Reimplement class caching, fix performance issue
This commit is contained in:
parent
35e37121f9
commit
fc5caf143d
@ -1,5 +1,6 @@
|
||||
package com.comphenix.protocol.reflect;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.GenericDeclaration;
|
||||
import java.lang.reflect.Member;
|
||||
@ -72,6 +73,16 @@ public abstract class MethodInfo implements GenericDeclaration, Member {
|
||||
public boolean isConstructor() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public <T extends Annotation> T getAnnotation(Class<T> clazz) {
|
||||
return method.getAnnotation(clazz);
|
||||
}
|
||||
public Annotation[] getAnnotations() {
|
||||
return method.getAnnotations();
|
||||
}
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
return method.getDeclaredAnnotations();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -152,6 +163,16 @@ public abstract class MethodInfo implements GenericDeclaration, Member {
|
||||
public boolean isConstructor() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public <T extends Annotation> T getAnnotation(Class<T> clazz) {
|
||||
return constructor.getAnnotation(clazz);
|
||||
}
|
||||
public Annotation[] getAnnotations() {
|
||||
return constructor.getAnnotations();
|
||||
}
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
return constructor.getAnnotations();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2012 Kristian S. Stangeland
|
||||
*
|
||||
@ -14,11 +14,11 @@
|
||||
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
package com.comphenix.protocol.utility;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Maps;
|
||||
@ -29,10 +29,10 @@ import com.google.common.collect.Maps;
|
||||
* @author Kristian
|
||||
*/
|
||||
class CachedPackage {
|
||||
private final Map<String, Class<?>> cache;
|
||||
private final Map<String, Optional<Class<?>>> cache;
|
||||
private final String packageName;
|
||||
private final ClassSource source;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a new cached package.
|
||||
* @param packageName - the name of the current package.
|
||||
@ -43,16 +43,20 @@ class CachedPackage {
|
||||
this.cache = Maps.newConcurrentMap();
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Associate a given class with a class name.
|
||||
* @param className - class name.
|
||||
* @param clazz - type of class.
|
||||
*/
|
||||
public void setPackageClass(String className, Class<?> clazz) {
|
||||
cache.put(className, clazz);
|
||||
if (clazz != null) {
|
||||
cache.put(className, Optional.<Class<?>> of(clazz));
|
||||
} else {
|
||||
cache.remove(className);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the class object of a specific class in the current package.
|
||||
* @param className - the specific class.
|
||||
@ -60,26 +64,33 @@ class CachedPackage {
|
||||
* @throws RuntimeException If we are unable to find the given class.
|
||||
*/
|
||||
public Class<?> getPackageClass(String className) {
|
||||
Preconditions.checkNotNull(className, "className cannot be null!");
|
||||
|
||||
// See if we've already looked it up
|
||||
if (cache.containsKey(className)) {
|
||||
Optional<Class<?>> result = cache.get(className);
|
||||
if (!result.isPresent()) {
|
||||
throw new RuntimeException("Cannot find class " + className);
|
||||
}
|
||||
|
||||
return result.get();
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> result = cache.get(Preconditions.checkNotNull(className, "className cannot be NULL"));
|
||||
|
||||
// Concurrency is not a problem - we don't care if we look up a class twice
|
||||
if (result == null) {
|
||||
// Look up the class dynamically
|
||||
result = source.loadClass(combine(packageName, className));
|
||||
|
||||
if (result == null)
|
||||
throw new IllegalArgumentException("Source " + source + " returned NULL for " + className);
|
||||
cache.put(className, result);
|
||||
}
|
||||
return result;
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
setPackageClass(className, null);
|
||||
throw new RuntimeException("Cannot find class " + className, e);
|
||||
// Try looking it up
|
||||
Class<?> clazz = source.loadClass(combine(packageName, className));
|
||||
if (clazz == null) {
|
||||
throw new IllegalArgumentException("Source " + source + " returned null for " + className);
|
||||
}
|
||||
|
||||
cache.put(className, Optional.<Class<?>> of(clazz));
|
||||
return clazz;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
cache.put(className, Optional.<Class<?>> absent());
|
||||
throw new RuntimeException("Cannot find class " + className, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Correctly combine a package name and the child class we're looking for.
|
||||
* @param packageName - name of the package, or an empty string for the default package.
|
||||
|
@ -942,6 +942,9 @@ public class MinecraftReflection {
|
||||
return getMinecraftClass("MinecraftServer");
|
||||
} catch (RuntimeException e) {
|
||||
useFallbackServer();
|
||||
|
||||
// Reset the cache and try again
|
||||
setMinecraftClass("MinecraftServer", null);
|
||||
return getMinecraftClass("MinecraftServer");
|
||||
}
|
||||
}
|
||||
@ -990,8 +993,10 @@ public class MinecraftReflection {
|
||||
try {
|
||||
return getMinecraftClass("ServerConfigurationManager", "PlayerList");
|
||||
} catch (RuntimeException e) {
|
||||
// Try again
|
||||
useFallbackServer();
|
||||
|
||||
// Reset cache and try again
|
||||
setMinecraftClass("ServerConfigurationManager", null);
|
||||
return getMinecraftClass("ServerConfigurationManager");
|
||||
}
|
||||
}
|
||||
@ -1578,6 +1583,9 @@ public class MinecraftReflection {
|
||||
} catch (RuntimeException e) {
|
||||
// Initialize first
|
||||
getAttributeSnapshotClass();
|
||||
|
||||
// Reset cache and try again
|
||||
setMinecraftClass("AttributeModifier", null);
|
||||
return getMinecraftClass("AttributeModifier");
|
||||
}
|
||||
}
|
||||
@ -1893,9 +1901,11 @@ public class MinecraftReflection {
|
||||
* @throws RuntimeException If we are unable to find the given class.
|
||||
*/
|
||||
public static Class<?> getCraftBukkitClass(String className) {
|
||||
return getClass(getCraftBukkitPackage() + "." + className);
|
||||
if (craftbukkitPackage == null)
|
||||
craftbukkitPackage = new CachedPackage(getCraftBukkitPackage(), getClassSource());
|
||||
return craftbukkitPackage.getPackageClass(className);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the class object of a specific Minecraft class.
|
||||
* @param className - the specific Minecraft class.
|
||||
@ -1903,30 +1913,9 @@ public class MinecraftReflection {
|
||||
* @throws RuntimeException If we are unable to find the given class.
|
||||
*/
|
||||
public static Class<?> getMinecraftClass(String className) {
|
||||
return getClass(getMinecraftPackage() + "." + className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the class object of a specific Minecraft library class.
|
||||
* @param className - the specific library Minecraft class.
|
||||
* @return Class object.
|
||||
* @throws RuntimeException If we are unable to find the given class.
|
||||
*/
|
||||
public static Class<?> getMinecraftLibraryClass(String className) {
|
||||
return getClass(getMinecraftLibraryPackage() + "." + className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the class object for the specific library class.
|
||||
* @param className - name of the Minecraft library class.
|
||||
* @param clazz - the new class object.
|
||||
* @return The provided clazz object.
|
||||
*/
|
||||
private static Class<?> setMinecraftLibraryClass(String className, Class<?> clazz) {
|
||||
if (libraryPackage == null)
|
||||
libraryPackage = new CachedPackage(getMinecraftLibraryPackage(), getClassSource());
|
||||
libraryPackage.setPackageClass(className, clazz);
|
||||
return clazz;
|
||||
if (minecraftPackage == null)
|
||||
minecraftPackage = new CachedPackage(getMinecraftPackage(), getClassSource());
|
||||
return minecraftPackage.getPackageClass(className);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1964,6 +1953,7 @@ public class MinecraftReflection {
|
||||
// Just use the default class loader
|
||||
classSource = ClassSource.fromClassLoader();
|
||||
}
|
||||
|
||||
return classSource;
|
||||
}
|
||||
|
||||
@ -1978,7 +1968,7 @@ public class MinecraftReflection {
|
||||
try {
|
||||
// Try the main class first
|
||||
return getMinecraftClass(className);
|
||||
} catch (RuntimeException e1) {
|
||||
} catch (RuntimeException e) {
|
||||
Class<?> success = null;
|
||||
|
||||
// Try every alias too
|
||||
@ -1986,8 +1976,8 @@ public class MinecraftReflection {
|
||||
try {
|
||||
success = getMinecraftClass(alias);
|
||||
break;
|
||||
} catch (RuntimeException e2) {
|
||||
// Swallov
|
||||
} catch (RuntimeException e1) {
|
||||
// e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1997,15 +1987,37 @@ public class MinecraftReflection {
|
||||
return success;
|
||||
} else {
|
||||
// Hack failed
|
||||
throw new RuntimeException(
|
||||
String.format("Unable to find %s (%s)",
|
||||
className,
|
||||
Joiner.on(", ").join(aliases))
|
||||
);
|
||||
throw new RuntimeException(String.format("Unable to find %s (%s)", className, Joiner.on(", ").join(aliases)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the class object of a specific Minecraft library class.
|
||||
* @param className - the specific library Minecraft class.
|
||||
* @return Class object.
|
||||
* @throws RuntimeException If we are unable to find the given class.
|
||||
*/
|
||||
public static Class<?> getMinecraftLibraryClass(String className) {
|
||||
if (libraryPackage == null)
|
||||
libraryPackage = new CachedPackage(getMinecraftLibraryPackage(), getClassSource());
|
||||
return libraryPackage.getPackageClass(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the class object for the specific library class.
|
||||
* @param className - name of the Minecraft library class.
|
||||
* @param clazz - the new class object.
|
||||
* @return The provided clazz object.
|
||||
*/
|
||||
private static Class<?> setMinecraftLibraryClass(String className, Class<?> clazz) {
|
||||
if (libraryPackage == null)
|
||||
libraryPackage = new CachedPackage(getMinecraftLibraryPackage(), getClassSource());
|
||||
libraryPackage.setPackageClass(className, clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dynamically retrieve the NetworkManager name.
|
||||
* @return Name of the NetworkManager class.
|
||||
|
Loading…
Reference in New Issue
Block a user