MessageAsmMethodBoost优化
This commit is contained in:
@@ -29,6 +29,7 @@ import static org.redkale.asm.Opcodes.LLOAD;
|
||||
import static org.redkale.asm.Opcodes.LRETURN;
|
||||
import static org.redkale.asm.Opcodes.RETURN;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.util.RedkaleClassLoader.DynBytesClassLoader;
|
||||
import org.redkale.util.Utility;
|
||||
|
||||
/**
|
||||
@@ -100,7 +101,7 @@ public abstract class AsmMethodBoost<T> {
|
||||
* @return 下一个新的方法名,不做任何处理应返回参数newMethodName
|
||||
*/
|
||||
public abstract AsmNewMethod doMethod(
|
||||
ClassLoader classLoader,
|
||||
DynBytesClassLoader classLoader,
|
||||
ClassWriter cw,
|
||||
Class serviceImplClass,
|
||||
String newDynName,
|
||||
@@ -117,7 +118,8 @@ public abstract class AsmMethodBoost<T> {
|
||||
* @param newDynName 动态新类名
|
||||
* @param fieldPrefix 动态字段的前缀
|
||||
*/
|
||||
public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {}
|
||||
public void doAfterMethods(
|
||||
DynBytesClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {}
|
||||
|
||||
/**
|
||||
* 实例对象进行操作,通常用于给动态的字段赋值
|
||||
@@ -126,7 +128,7 @@ public abstract class AsmMethodBoost<T> {
|
||||
* @param resourceFactory ResourceFactory
|
||||
* @param service 实例对象
|
||||
*/
|
||||
public abstract void doInstance(ClassLoader classLoader, ResourceFactory resourceFactory, T service);
|
||||
public abstract void doInstance(DynBytesClassLoader classLoader, ResourceFactory resourceFactory, T service);
|
||||
|
||||
protected AsmMethodBean getMethodBean(Method method) {
|
||||
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
|
||||
@@ -306,7 +308,7 @@ public abstract class AsmMethodBoost<T> {
|
||||
|
||||
@Override
|
||||
public AsmNewMethod doMethod(
|
||||
ClassLoader classLoader,
|
||||
DynBytesClassLoader classLoader,
|
||||
ClassWriter cw,
|
||||
Class serviceImplClass,
|
||||
String newDynName,
|
||||
@@ -325,7 +327,8 @@ public abstract class AsmMethodBoost<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {
|
||||
public void doAfterMethods(
|
||||
DynBytesClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {
|
||||
for (AsmMethodBoost item : items) {
|
||||
if (item != null) {
|
||||
item.doAfterMethods(classLoader, cw, newDynName, fieldPrefix);
|
||||
@@ -334,7 +337,7 @@ public abstract class AsmMethodBoost<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doInstance(ClassLoader classLoader, ResourceFactory resourceFactory, T service) {
|
||||
public void doInstance(DynBytesClassLoader classLoader, ResourceFactory resourceFactory, T service) {
|
||||
for (AsmMethodBoost item : items) {
|
||||
if (item != null) {
|
||||
item.doInstance(classLoader, resourceFactory, service);
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.redkale.cached.Cached;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.service.LoadMode;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
import org.redkale.util.RedkaleClassLoader.DynBytesClassLoader;
|
||||
import org.redkale.util.RedkaleException;
|
||||
import org.redkale.util.ThrowSupplier;
|
||||
import org.redkale.util.TypeToken;
|
||||
@@ -62,7 +63,7 @@ public class CachedAsmMethodBoost extends AsmMethodBoost {
|
||||
|
||||
@Override
|
||||
public AsmNewMethod doMethod(
|
||||
final ClassLoader classLoader,
|
||||
final DynBytesClassLoader classLoader,
|
||||
final ClassWriter cw,
|
||||
final Class serviceImplClass,
|
||||
final String newDynName,
|
||||
@@ -215,7 +216,7 @@ public class CachedAsmMethodBoost extends AsmMethodBoost {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doInstance(ClassLoader classLoader, ResourceFactory resourceFactory, Object service) {
|
||||
public void doInstance(DynBytesClassLoader classLoader, ResourceFactory resourceFactory, Object service) {
|
||||
Class clazz = service.getClass();
|
||||
if (actionMap == null) { // 为null表示没有调用过doMethod, 动态类在编译是已经生成好了
|
||||
actionMap = new LinkedHashMap<>();
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.redkale.asm.Type;
|
||||
import org.redkale.inject.ResourceFactory;
|
||||
import org.redkale.locked.Locked;
|
||||
import org.redkale.service.LoadMode;
|
||||
import org.redkale.util.RedkaleClassLoader.DynBytesClassLoader;
|
||||
import org.redkale.util.RedkaleException;
|
||||
|
||||
/** @author zhangjx */
|
||||
@@ -38,7 +39,7 @@ public class LockedAsmMethodBoost extends AsmMethodBoost {
|
||||
|
||||
@Override
|
||||
public AsmNewMethod doMethod(
|
||||
ClassLoader classLoader,
|
||||
DynBytesClassLoader classLoader,
|
||||
ClassWriter cw,
|
||||
Class serviceImplClass,
|
||||
String newDynName,
|
||||
@@ -90,12 +91,12 @@ public class LockedAsmMethodBoost extends AsmMethodBoost {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {
|
||||
public void doAfterMethods(DynBytesClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doInstance(ClassLoader classLoader, ResourceFactory resourceFactory, Object service) {
|
||||
public void doInstance(DynBytesClassLoader classLoader, ResourceFactory resourceFactory, Object service) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -50,8 +49,10 @@ import org.redkale.mq.MessageConext;
|
||||
import org.redkale.mq.MessageConsumer;
|
||||
import org.redkale.mq.Messaged;
|
||||
import org.redkale.mq.ResourceConsumer;
|
||||
import org.redkale.mq.spi.DynForMessaged.DynForMessageds;
|
||||
import org.redkale.service.LoadMode;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
import org.redkale.util.RedkaleClassLoader.DynBytesClassLoader;
|
||||
import org.redkale.util.RedkaleException;
|
||||
import org.redkale.util.TypeToken;
|
||||
import org.redkale.util.Utility;
|
||||
@@ -67,8 +68,6 @@ public class MessageAsmMethodBoost extends AsmMethodBoost {
|
||||
|
||||
private Map<String, AsmMethodBean> methodBeans;
|
||||
|
||||
private RedkaleClassLoader.DynBytesClassLoader newLoader;
|
||||
|
||||
private Map<String, byte[]> consumerBytes;
|
||||
|
||||
public MessageAsmMethodBoost(boolean remote, Class serviceType, MessageModuleEngine messageEngine) {
|
||||
@@ -83,7 +82,7 @@ public class MessageAsmMethodBoost extends AsmMethodBoost {
|
||||
|
||||
@Override
|
||||
public AsmNewMethod doMethod(
|
||||
ClassLoader classLoader,
|
||||
DynBytesClassLoader classLoader,
|
||||
ClassWriter cw,
|
||||
Class serviceImplClass,
|
||||
String newDynName,
|
||||
@@ -324,55 +323,41 @@ public class MessageAsmMethodBoost extends AsmMethodBoost {
|
||||
if (consumerBytes == null) {
|
||||
consumerBytes = new LinkedHashMap<>();
|
||||
}
|
||||
consumerBytes.put(innerFullName.replace('/', '.'), bytes);
|
||||
consumerBytes.put(innerFullName, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterMethods(ClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {
|
||||
public void doAfterMethods(DynBytesClassLoader classLoader, ClassWriter cw, String newDynName, String fieldPrefix) {
|
||||
if (Utility.isNotEmpty(consumerBytes)) {
|
||||
AnnotationVisitor av =
|
||||
cw.visitAnnotation(org.redkale.asm.Type.getDescriptor(DynForMessaged.class), true);
|
||||
av.visit("value", org.redkale.asm.Type.getType("L" + newDynName.replace('.', '/') + ";"));
|
||||
av.visitEnd();
|
||||
AnnotationVisitor av0 = cw.visitAnnotation(org.redkale.asm.Type.getDescriptor(DynForMessageds.class), true);
|
||||
AnnotationVisitor av1 = av0.visitArray("value");
|
||||
consumerBytes.forEach((innerFullName, bytes) -> {
|
||||
String clzName = innerFullName.replace('/', '.');
|
||||
Class clazz = classLoader.loadClass(clzName, bytes);
|
||||
RedkaleClassLoader.putDynClass(clzName, bytes, clazz);
|
||||
AnnotationVisitor av2 =
|
||||
av1.visitAnnotation(null, org.redkale.asm.Type.getDescriptor(DynForMessaged.class));
|
||||
av2.visit("value", org.redkale.asm.Type.getType("L" + innerFullName + ";"));
|
||||
av2.visitEnd();
|
||||
});
|
||||
av1.visitEnd();
|
||||
av0.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doInstance(ClassLoader classLoader, ResourceFactory resourceFactory, Object service) {
|
||||
public void doInstance(DynBytesClassLoader classLoader, ResourceFactory resourceFactory, Object service) {
|
||||
DynForMessaged[] dyns = service.getClass().getAnnotationsByType(DynForMessaged.class);
|
||||
if (Utility.isEmpty(dyns)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (Utility.isNotEmpty(consumerBytes)) {
|
||||
if (newLoader == null) {
|
||||
if (classLoader instanceof RedkaleClassLoader.DynBytesClassLoader) {
|
||||
newLoader = (RedkaleClassLoader.DynBytesClassLoader) classLoader;
|
||||
} else {
|
||||
newLoader = new RedkaleClassLoader.DynBytesClassLoader(
|
||||
classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader);
|
||||
}
|
||||
}
|
||||
List<Class<? extends MessageConsumer>> consumers = new ArrayList<>();
|
||||
consumerBytes.forEach((clzName, bytes) -> {
|
||||
Class<? extends MessageConsumer> clazz = (Class) newLoader.loadClass(clzName, bytes);
|
||||
RedkaleClassLoader.putDynClass(clzName, bytes, clazz);
|
||||
consumers.add(clazz);
|
||||
});
|
||||
for (Class<? extends MessageConsumer> clazz : consumers) {
|
||||
MessageConsumer consumer = (MessageConsumer) clazz.getConstructors()[0].newInstance(service);
|
||||
messageEngine.addMessageConsumer(consumer);
|
||||
}
|
||||
} else {
|
||||
if (Utility.isNotEmpty(dyns)) {
|
||||
try {
|
||||
for (DynForMessaged item : dyns) {
|
||||
Class<? extends MessageConsumer> clazz = item.value();
|
||||
MessageConsumer consumer = (MessageConsumer) clazz.getConstructors()[0].newInstance(service);
|
||||
messageEngine.addMessageConsumer(consumer);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RedkaleException(e);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RedkaleException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.redkale.scheduled.Scheduled;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.util.AnyValue;
|
||||
import org.redkale.util.RedkaleClassLoader;
|
||||
import org.redkale.util.RedkaleClassLoader.DynBytesClassLoader;
|
||||
import org.redkale.util.TypeToken;
|
||||
import org.redkale.util.Uint128;
|
||||
import org.redkale.util.Utility;
|
||||
@@ -493,7 +494,7 @@ public abstract class Sncp {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static <T extends Service> Class<? extends T> createLocalServiceClass(
|
||||
ClassLoader classLoader,
|
||||
DynBytesClassLoader dynLoader,
|
||||
final String name,
|
||||
final Class<T> serviceImplClass,
|
||||
final AsmMethodBoost methodBoost) {
|
||||
@@ -513,7 +514,6 @@ public abstract class Sncp {
|
||||
final String resDesc = Type.getDescriptor(Resource.class);
|
||||
final String anyValueDesc = Type.getDescriptor(AnyValue.class);
|
||||
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
|
||||
ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
|
||||
// String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + LOCALPREFIX +
|
||||
// serviceImplClass.getSimpleName();
|
||||
String newDynName = "org/redkaledyn/service/local/_DynLocalService__"
|
||||
@@ -533,7 +533,7 @@ public abstract class Sncp {
|
||||
if (methodBoost == null) { // 加强动态时不能重复加载
|
||||
try {
|
||||
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
|
||||
return (Class<T>) (clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz);
|
||||
return (Class<T>) (clz == null ? dynLoader.loadClass(newDynName.replace('/', '.')) : clz);
|
||||
} catch (ClassNotFoundException e) {
|
||||
// do nothing
|
||||
} catch (Throwable t) {
|
||||
@@ -595,8 +595,8 @@ public abstract class Sncp {
|
||||
mv.visitEnd();
|
||||
}
|
||||
if (methodBoost != null) {
|
||||
createNewMethods(classLoader, serviceImplClass, methodBoost, new HashSet<>(), cw, newDynName, supDynName);
|
||||
methodBoost.doAfterMethods(classLoader, cw, newDynName, FIELDPREFIX);
|
||||
createNewMethods(dynLoader, serviceImplClass, methodBoost, new HashSet<>(), cw, newDynName, supDynName);
|
||||
methodBoost.doAfterMethods(dynLoader, cw, newDynName, FIELDPREFIX);
|
||||
}
|
||||
cw.visitEnd();
|
||||
byte[] bytes = cw.toByteArray();
|
||||
@@ -604,17 +604,13 @@ public abstract class Sncp {
|
||||
if (methodBoost != null) {
|
||||
try {
|
||||
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
|
||||
newClazz = (clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz);
|
||||
newClazz = (clz == null ? dynLoader.loadClass(newDynName.replace('/', '.')) : clz);
|
||||
} catch (Throwable t) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
if (newClazz == null) {
|
||||
newClazz = new ClassLoader(loader) {
|
||||
public final Class<?> loadClass(String name, byte[] b) {
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
newClazz = dynLoader.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
}
|
||||
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
|
||||
RedkaleClassLoader.putReflectionPublicClasses(newDynName.replace('/', '.'));
|
||||
@@ -637,7 +633,7 @@ public abstract class Sncp {
|
||||
}
|
||||
|
||||
private static void createNewMethods(
|
||||
ClassLoader classLoader,
|
||||
DynBytesClassLoader classLoader,
|
||||
Class clazz,
|
||||
final AsmMethodBoost methodBoost,
|
||||
Set<String> methodKeys,
|
||||
@@ -777,7 +773,8 @@ public abstract class Sncp {
|
||||
final String remoteGroup,
|
||||
final AnyValue conf) {
|
||||
try {
|
||||
final Class newClazz = createLocalServiceClass(classLoader, name, serviceImplClass, methodBoost);
|
||||
final DynBytesClassLoader dynLoader = DynBytesClassLoader.create(classLoader);
|
||||
final Class newClazz = createLocalServiceClass(dynLoader, name, serviceImplClass, methodBoost);
|
||||
T service = (T) newClazz.getDeclaredConstructor().newInstance();
|
||||
// --------------------------------------
|
||||
Service remoteService = null;
|
||||
@@ -829,7 +826,7 @@ public abstract class Sncp {
|
||||
}
|
||||
if (methodBoost != null) {
|
||||
// 必须用servcie的ClassLoader, 因为service是动态ClassLoader会与doMethod里的动态ClassLoader不一致
|
||||
methodBoost.doInstance(service.getClass().getClassLoader(), resourceFactory, service);
|
||||
methodBoost.doInstance(dynLoader, resourceFactory, service);
|
||||
}
|
||||
return service;
|
||||
} catch (RuntimeException rex) {
|
||||
@@ -949,7 +946,7 @@ public abstract class Sncp {
|
||||
final String sncpInfoDesc = Type.getDescriptor(SncpRemoteInfo.class);
|
||||
final String sncpDynDesc = Type.getDescriptor(SncpDyn.class);
|
||||
final String anyValueDesc = Type.getDescriptor(AnyValue.class);
|
||||
final ClassLoader loader = classLoader == null ? Thread.currentThread().getContextClassLoader() : classLoader;
|
||||
final DynBytesClassLoader dynLoader = DynBytesClassLoader.create(classLoader);
|
||||
String newDynName = "org/redkaledyn/service/remote/_DynRemoteService__"
|
||||
+ serviceTypeOrImplClass.getName().replace('.', '_').replace('$', '_');
|
||||
if (!name.isEmpty()) {
|
||||
@@ -966,7 +963,7 @@ public abstract class Sncp {
|
||||
}
|
||||
try {
|
||||
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
|
||||
Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz;
|
||||
Class newClazz = clz == null ? dynLoader.loadClass(newDynName.replace('/', '.')) : clz;
|
||||
T service = (T) newClazz.getDeclaredConstructor().newInstance();
|
||||
{
|
||||
Field c = newClazz.getDeclaredField(FIELDPREFIX + "_conf");
|
||||
@@ -985,7 +982,7 @@ public abstract class Sncp {
|
||||
}
|
||||
if (methodBoost != null) {
|
||||
// 必须用servcie的ClassLoader, 因为service是动态ClassLoader会与doMethod里的动态ClassLoader不一致
|
||||
methodBoost.doInstance(service.getClass().getClassLoader(), resourceFactory, service);
|
||||
methodBoost.doInstance(dynLoader, resourceFactory, service);
|
||||
}
|
||||
return service;
|
||||
} catch (Throwable ex) {
|
||||
@@ -1111,7 +1108,7 @@ public abstract class Sncp {
|
||||
if (methodBoost != null) {
|
||||
List<Class<? extends Annotation>> filterAnns = methodBoost.filterMethodAnnotations(method);
|
||||
newMethod = methodBoost.doMethod(
|
||||
classLoader, cw, serviceTypeOrImplClass, newDynName, FIELDPREFIX, filterAnns, method, null);
|
||||
dynLoader, cw, serviceTypeOrImplClass, newDynName, FIELDPREFIX, filterAnns, method, null);
|
||||
}
|
||||
if (newMethod != null) {
|
||||
acc = newMethod.getMethodAccs();
|
||||
@@ -1238,16 +1235,12 @@ public abstract class Sncp {
|
||||
mv.visitEnd();
|
||||
}
|
||||
if (methodBoost != null) {
|
||||
createNewMethods(classLoader, serviceTypeOrImplClass, methodBoost, methodKeys, cw, newDynName, supDynName);
|
||||
methodBoost.doAfterMethods(classLoader, cw, newDynName, FIELDPREFIX);
|
||||
createNewMethods(dynLoader, serviceTypeOrImplClass, methodBoost, methodKeys, cw, newDynName, supDynName);
|
||||
methodBoost.doAfterMethods(dynLoader, cw, newDynName, FIELDPREFIX);
|
||||
}
|
||||
cw.visitEnd();
|
||||
byte[] bytes = cw.toByteArray();
|
||||
Class<?> newClazz = new ClassLoader(loader) {
|
||||
public final Class<?> loadClass(String name, byte[] b) {
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
Class<?> newClazz = dynLoader.loadClass(newDynName.replace('/', '.'), bytes);
|
||||
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
|
||||
RedkaleClassLoader.putReflectionPublicConstructors(newClazz, newDynName.replace('/', '.'));
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
|
||||
@@ -1273,7 +1266,7 @@ public abstract class Sncp {
|
||||
}
|
||||
if (methodBoost != null) {
|
||||
// 必须用servcie的ClassLoader, 因为service是动态ClassLoader会与doMethod里的动态ClassLoader不一致
|
||||
methodBoost.doInstance(service.getClass().getClassLoader(), resourceFactory, service);
|
||||
methodBoost.doInstance(dynLoader, resourceFactory, service);
|
||||
}
|
||||
return service;
|
||||
} catch (Exception ex) {
|
||||
|
||||
@@ -587,6 +587,15 @@ public class RedkaleClassLoader extends URLClassLoader {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
public static DynBytesClassLoader create(ClassLoader parent) {
|
||||
if (parent == null) {
|
||||
parent = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
return parent instanceof DynBytesClassLoader
|
||||
? (DynBytesClassLoader) parent
|
||||
: new DynBytesClassLoader(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
byte[] classData = classes.get(name);
|
||||
|
||||
Reference in New Issue
Block a user