From a8b83823dcfe9e38dd97d4a0f862d1726c7ab8a3 Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Thu, 16 Nov 2023 15:56:25 +0800 Subject: [PATCH] Fix generic type result copy in InjvmInvoker (#13351) --- .../injvm/DefaultParamDeepCopyUtil.java | 9 +++- .../rpc/protocol/injvm/InjvmInvoker.java | 49 ++++++++++++++----- .../rpc/protocol/injvm/ParamDeepCopyUtil.java | 8 ++- 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/DefaultParamDeepCopyUtil.java b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/DefaultParamDeepCopyUtil.java index 0b6ede8afe9..4f5243e6557 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/DefaultParamDeepCopyUtil.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/DefaultParamDeepCopyUtil.java @@ -27,6 +27,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.lang.reflect.Type; import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_ERROR_DESERIALIZE; @@ -38,7 +39,7 @@ public class DefaultParamDeepCopyUtil implements ParamDeepCopyUtil { @Override @SuppressWarnings({"unchecked"}) - public T copy(URL url, Object src, Class targetClass) { + public T copy(URL url, Object src, Class targetClass, Type type) { Serialization serialization = url.getOrDefaultFrameworkModel() .getExtensionLoader(Serialization.class) .getExtension(UrlUtils.serializationOrDefault(url)); @@ -50,7 +51,11 @@ public T copy(URL url, Object src, Class targetClass) { try (ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray())) { ObjectInput objectInput = serialization.deserialize(url, inputStream); - return objectInput.readObject(targetClass); + if (type != null) { + return objectInput.readObject(targetClass, type); + } else { + return objectInput.readObject(targetClass); + } } catch (ClassNotFoundException | IOException e) { logger.error(PROTOCOL_ERROR_DESERIALIZE, "", "", "Unable to deep copy parameter to target class.", e); } diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java index 8712d202300..68054d7ddb7 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java @@ -152,7 +152,7 @@ public Result doInvoke(Invocation invocation) throws Throwable { appResponse.setObjectAttachments(new HashMap<>(result.getObjectAttachments())); return appResponse; } else { - rebuildValue(invocation, desc, result); + rebuildValue(invocation, invoker, result); AppResponse appResponse = new AppResponse(result.getValue()); appResponse.setObjectAttachments(new HashMap<>(result.getObjectAttachments())); return appResponse; @@ -190,7 +190,7 @@ public Result doInvoke(Invocation invocation) throws Throwable { if (r.hasException()) { rpcResult.setException(r.getException()); } else { - Object rebuildValue = rebuildValue(invocation, desc, r.getValue()); + Object rebuildValue = rebuildValue(invocation, invoker, r.getValue()); rpcResult.setValue(rebuildValue); } } @@ -201,7 +201,7 @@ public Result doInvoke(Invocation invocation) throws Throwable { if (result.hasException()) { rpcResult.setException(result.getException()); } else { - Object rebuildValue = rebuildValue(invocation, desc, result.getValue()); + Object rebuildValue = rebuildValue(invocation, invoker, result.getValue()); rpcResult.setValue(rebuildValue); } rpcResult.setObjectAttachments(new HashMap<>(result.getObjectAttachments())); @@ -232,11 +232,7 @@ private Invocation recreateInvocation(Invocation invocation, Invoker invoker, } String methodName = invocation.getMethodName(); - ServiceModel consumerServiceModel = invocation.getServiceModel(); - boolean shouldSkip = shouldIgnoreSameModule - && consumerServiceModel != null - && Objects.equals(providerServiceModel.getModuleModel(), consumerServiceModel.getModuleModel()); - if (CommonConstants.$INVOKE.equals(methodName) || shouldSkip) { + if (isSkipCopy(invocation, invoker)) { // generic invoke, skip copy arguments RpcInvocation copiedInvocation = new RpcInvocation( invocation.getTargetServiceUniqueName(), @@ -297,16 +293,43 @@ private Invocation recreateInvocation(Invocation invocation, Invoker invoker, } } - private Object rebuildValue(Invocation invocation, String desc, Object originValue) { + private boolean isSkipCopy(Invocation invocation, Invoker invoker) { + ServiceModel providerServiceModel = invoker.getUrl().getServiceModel(); + + if (providerServiceModel == null) { + return true; + } + String methodName = invocation.getMethodName(); + + ServiceModel consumerServiceModel = invocation.getServiceModel(); + boolean shouldSkip = shouldIgnoreSameModule + && consumerServiceModel != null + && Objects.equals(providerServiceModel.getModuleModel(), consumerServiceModel.getModuleModel()); + + return CommonConstants.$INVOKE.equals(methodName) + || CommonConstants.$INVOKE_ASYNC.equals(methodName) + || shouldSkip; + } + + private Object rebuildValue(Invocation invocation, Invoker invoker, Object originValue) { + if (isSkipCopy(invocation, invoker)) { + return originValue; + } + Object value = originValue; ClassLoader cl = Thread.currentThread().getContextClassLoader(); try { ServiceModel consumerServiceModel = getUrl().getServiceModel(); if (consumerServiceModel != null) { - Class returnType = getReturnType(consumerServiceModel, invocation.getMethodName(), desc); - if (returnType != null) { - Thread.currentThread().setContextClassLoader(consumerServiceModel.getClassLoader()); - value = paramDeepCopyUtil.copy(consumerUrl, originValue, returnType); + Thread.currentThread().setContextClassLoader(consumerServiceModel.getClassLoader()); + Type[] returnTypes = RpcUtils.getReturnTypes(invocation); + if (returnTypes == null) { + return originValue; + } + if (returnTypes.length == 1) { + value = paramDeepCopyUtil.copy(consumerUrl, originValue, (Class) returnTypes[0]); + } else if (returnTypes.length == 2) { + value = paramDeepCopyUtil.copy(consumerUrl, originValue, (Class) returnTypes[0], returnTypes[1]); } } return value; diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/ParamDeepCopyUtil.java b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/ParamDeepCopyUtil.java index c76a5a16dcc..1e76789b91b 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/ParamDeepCopyUtil.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/ParamDeepCopyUtil.java @@ -20,8 +20,14 @@ import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; +import java.lang.reflect.Type; + @SPI(scope = ExtensionScope.FRAMEWORK) public interface ParamDeepCopyUtil { - T copy(URL url, Object src, Class targetClass); + default T copy(URL url, Object src, Class targetClass) { + return copy(url, src, targetClass, null); + } + + T copy(URL url, Object src, Class targetClass, Type type); }