MessageAsmMethodBoost优化

This commit is contained in:
redkale
2024-08-13 01:36:28 +08:00
parent aee5745172
commit a51141d497
6 changed files with 67 additions and 75 deletions

View File

@@ -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);

View File

@@ -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<>();

View File

@@ -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
}
}

View File

@@ -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);
}
}
}

View File

@@ -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) {

View File

@@ -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);