Skip to content

Commit 75ec578

Browse files
authored
Merge pull request quarkusio#50366 from Ladicek/arc-fix-construction-of-interception-proxies
ArC: fix construction of interception proxies, part 2
2 parents 78b3174 + eb84c1c commit 75ec578

File tree

3 files changed

+30
-12
lines changed

3 files changed

+30
-12
lines changed

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ClientProxyGenerator.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,13 @@ Collection<Resource> generate(BeanInfo bean, String beanClassName,
184184

185185
if (!superClass.equals(Object.class.getName())) {
186186
// Skip delegation if proxy is not constructed yet
187-
// This check is unnecessary for producers that return an interface
187+
// This is not necessary for producers of interfaces, because interfaces cannot have constructors
188+
// Similarly, this is not necessary for producers of `Object`, because its constructor does nothing
188189
// if(!this.bean == null) return super.foo()
189190
BytecodeCreator notConstructed = forward
190191
.ifNull(forward.readInstanceField(beanField.getFieldDescriptor(), forward.getThis())).trueBranch();
191-
if (Modifier.isAbstract(method.flags())) {
192-
notConstructed.throwException(IllegalStateException.class, "Cannot delegate to an abstract method");
192+
if (method.isAbstract()) {
193+
notConstructed.throwException(IllegalStateException.class, "Cannot invoke abstract method");
193194
} else {
194195
MethodDescriptor superDescriptor = MethodDescriptor.ofMethod(superClass, method.name(),
195196
method.returnType().name().toString(),

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InterceptionProxyGenerator.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ private void createInterceptionSubclass(ClassOutput classOutput, InterceptionPro
201201

202202
for (MethodInfo method : pseudoBean.getInterceptedMethods().keySet()) {
203203
forwardingMethods.put(MethodDescriptor.of(method), SubclassGenerator.createForwardingMethod(clazz,
204-
pseudoBeanClassName, method));
204+
pseudoBeanClassName, method, isInterface));
205205
}
206206

207207
FieldCreator constructedField = clazz.getFieldCreator(SubclassGenerator.FIELD_NAME_CONSTRUCTED, boolean.class)
@@ -369,9 +369,22 @@ private void createInterceptionSubclass(ClassOutput classOutput, InterceptionPro
369369
args[i] = mc.getMethodParam(i);
370370
}
371371

372-
BytecodeCreator notConstructed = mc.ifFalse(
373-
mc.readInstanceField(constructedField.getFieldDescriptor(), mc.getThis())).trueBranch();
374-
notConstructed.returnValue(notConstructed.invokeSpecialMethod(method, notConstructed.getThis(), args));
372+
if (!superClass.equals(Object.class.getName())) {
373+
// Skip delegation if proxy is not constructed yet
374+
// This is not necessary when intercepting interfaces, because interfaces cannot have constructors
375+
// Similarly, this is not necessary when intercepting `Object`, because its constructor does nothing
376+
BytecodeCreator notConstructed = mc.ifFalse(
377+
mc.readInstanceField(constructedField.getFieldDescriptor(), mc.getThis())).trueBranch();
378+
if (method.isAbstract()) {
379+
notConstructed.throwException(IllegalStateException.class, "Cannot invoke abstract method");
380+
} else {
381+
MethodDescriptor superDescriptor = MethodDescriptor.ofMethod(superClass, method.name(),
382+
method.returnType().name().toString(),
383+
method.parameterTypes().stream().map(p -> p.name().toString()).toArray());
384+
notConstructed.returnValue(
385+
notConstructed.invokeSpecialMethod(superDescriptor, notConstructed.getThis(), args));
386+
}
387+
}
375388

376389
ResultHandle dlgt = mc.readInstanceField(delegate.getFieldDescriptor(), mc.getThis());
377390
ResultHandle result = method.declaringClass().isInterface()

independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/SubclassGenerator.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ protected FieldDescriptor createConstructor(ClassOutput classOutput, BeanInfo be
190190
Map<MethodDescriptor, MethodDescriptor> forwardingMethods = new HashMap<>();
191191
List<MethodInfo> interceptedOrDecoratedMethods = bean.getInterceptedOrDecoratedMethods();
192192
for (MethodInfo method : interceptedOrDecoratedMethods) {
193-
forwardingMethods.put(MethodDescriptor.of(method), createForwardingMethod(subclass, providerTypeName, method));
193+
forwardingMethods.put(MethodDescriptor.of(method),
194+
createForwardingMethod(subclass, providerTypeName, method, false));
194195
}
195196

196197
// If a decorator is associated:
@@ -862,7 +863,8 @@ private boolean isDecorated(Set<MethodDescriptor> decoratedMethodDescriptors, Me
862863
return false;
863864
}
864865

865-
static MethodDescriptor createForwardingMethod(ClassCreator subclass, String providerTypeName, MethodInfo method) {
866+
static MethodDescriptor createForwardingMethod(ClassCreator subclass, String providerTypeName, MethodInfo method,
867+
boolean isInterface) {
866868
MethodDescriptor methodDescriptor = MethodDescriptor.of(method);
867869
String forwardMethodName = method.name() + "$$superforward";
868870
MethodDescriptor forwardDescriptor = MethodDescriptor.ofMethod(subclass.getClassName(), forwardMethodName,
@@ -876,7 +878,9 @@ static MethodDescriptor createForwardingMethod(ClassCreator subclass, String pro
876878
}
877879
MethodDescriptor virtualMethod = MethodDescriptor.ofMethod(providerTypeName, methodDescriptor.getName(),
878880
methodDescriptor.getReturnType(), methodDescriptor.getParameterTypes());
879-
forward.returnValue(forward.invokeSpecialMethod(virtualMethod, forward.getThis(), params));
881+
forward.returnValue(isInterface
882+
? forward.invokeSpecialInterfaceMethod(virtualMethod, forward.getThis(), params)
883+
: forward.invokeSpecialMethod(virtualMethod, forward.getThis(), params));
880884
return forwardDescriptor;
881885
}
882886

@@ -908,8 +912,8 @@ static void createInterceptedMethod(MethodInfo method, ClassCreator subclass, Fi
908912
for (int i = 0; i < parameters.size(); ++i) {
909913
params[i] = notConstructed.getMethodParam(i);
910914
}
911-
if (Modifier.isAbstract(method.flags())) {
912-
notConstructed.throwException(IllegalStateException.class, "Cannot delegate to an abstract method");
915+
if (method.isAbstract()) {
916+
notConstructed.throwException(IllegalStateException.class, "Cannot invoke abstract method");
913917
} else {
914918
notConstructed.returnValue(notConstructed.invokeVirtualMethod(forwardMethod, notConstructed.getThis(), params));
915919
}

0 commit comments

Comments
 (0)