• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / jmockit1 / 758

15 Mar 2026 03:43AM UTC coverage: 74.062% (+0.07%) from 73.988%
758

push

github

web-flow
Merge pull request #478 from hazendaz/copilot/check-issue-133-status

Fix constructor faking for `this()`-delegation constructors where argument creation throws

5913 of 8490 branches covered (69.65%)

Branch coverage included in aggregate %.

99 of 110 new or added lines in 2 files covered. (90.0%)

12424 of 16269 relevant lines covered (76.37%)

0.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.95
/main/src/main/java/mockit/internal/faking/FakedClassModifier.java
1
/*
2
 * MIT License
3
 * Copyright (c) 2006-2025 JMockit developers
4
 * See LICENSE file for full license text.
5
 */
6
package mockit.internal.faking;
7

8
import static java.lang.reflect.Modifier.isAbstract;
9
import static java.lang.reflect.Modifier.isNative;
10
import static java.lang.reflect.Modifier.isPublic;
11
import static java.lang.reflect.Modifier.isStatic;
12

13
import static mockit.asm.jvmConstants.Opcodes.ACONST_NULL;
14
import static mockit.asm.jvmConstants.Opcodes.ALOAD;
15
import static mockit.asm.jvmConstants.Opcodes.CHECKCAST;
16
import static mockit.asm.jvmConstants.Opcodes.DUP;
17
import static mockit.asm.jvmConstants.Opcodes.DUP_X1;
18
import static mockit.asm.jvmConstants.Opcodes.IFEQ;
19
import static mockit.asm.jvmConstants.Opcodes.IFNE;
20
import static mockit.asm.jvmConstants.Opcodes.IF_ACMPEQ;
21
import static mockit.asm.jvmConstants.Opcodes.ILOAD;
22
import static mockit.asm.jvmConstants.Opcodes.INSTANCEOF;
23
import static mockit.asm.jvmConstants.Opcodes.INVOKESPECIAL;
24
import static mockit.asm.jvmConstants.Opcodes.INVOKESTATIC;
25
import static mockit.asm.jvmConstants.Opcodes.INVOKEVIRTUAL;
26
import static mockit.asm.jvmConstants.Opcodes.IRETURN;
27
import static mockit.asm.jvmConstants.Opcodes.POP;
28
import static mockit.asm.jvmConstants.Opcodes.RETURN;
29
import static mockit.asm.jvmConstants.Opcodes.SIPUSH;
30

31
import edu.umd.cs.findbugs.annotations.NonNull;
32
import edu.umd.cs.findbugs.annotations.Nullable;
33

34
import mockit.MockUp;
35
import mockit.asm.classes.ClassReader;
36
import mockit.asm.controlFlow.Label;
37
import mockit.asm.jvmConstants.Access;
38
import mockit.asm.methods.MethodVisitor;
39
import mockit.asm.types.JavaType;
40
import mockit.asm.types.ReferenceType;
41
import mockit.internal.BaseClassModifier;
42
import mockit.internal.faking.FakeMethods.FakeMethod;
43
import mockit.internal.state.TestRun;
44
import mockit.internal.util.ClassLoad;
45

46
import org.checkerframework.checker.index.qual.NonNegative;
47

48
/**
49
 * Responsible for generating all necessary bytecode in the redefined (real) class. Such code will redirect calls made
50
 * on "real" methods to equivalent calls on the corresponding "fake" methods. The original code won't be executed by the
51
 * running JVM until the class redefinition is undone.
52
 * <p>
53
 * Methods in the real class with no corresponding fake methods are unaffected.
54
 * <p>
55
 * Any fields (static or not) in the real class remain untouched.
56
 */
57
final class FakedClassModifier extends BaseClassModifier {
58
    private static final int ABSTRACT_OR_SYNTHETIC = Access.ABSTRACT + Access.SYNTHETIC;
59

60
    @NonNull
61
    private final FakeMethods fakeMethods;
62
    private final boolean useClassLoadingBridgeForUpdatingFakeState;
63
    @NonNull
64
    private final Class<?> fakedClass;
65
    private FakeMethod fakeMethod;
66
    private boolean isConstructor;
67

68
    /**
69
     * Initializes the modifier for a given real/fake class pair.
70
     * <p>
71
     * The fake instance provided will receive calls for any instance methods defined in the fake class. Therefore, it
72
     * needs to be later recovered by the modified bytecode inside the real method. To enable this, the fake instance is
73
     * added to a global data structure made available through the {@link TestRun#getFake(String, Object)} method.
74
     *
75
     * @param cr
76
     *            the class file reader for the real class
77
     * @param realClass
78
     *            the class to be faked, or a base type of an implementation class to be faked
79
     * @param fake
80
     *            an instance of the fake class
81
     * @param fakeMethods
82
     *            contains the set of fake methods collected from the fake class; each fake method is identified by a
83
     *            pair composed of "name" and "desc", where "name" is the method name, and "desc" is the JVM internal
84
     *            description of the parameters; once the real class modification is complete this set will be empty,
85
     *            unless no corresponding real method was found for any of its method identifiers
86
     */
87
    FakedClassModifier(@NonNull ClassReader cr, @NonNull Class<?> realClass, @NonNull MockUp<?> fake,
88
            @NonNull FakeMethods fakeMethods) {
89
        super(cr);
1✔
90
        fakedClass = realClass;
1✔
91
        this.fakeMethods = fakeMethods;
1✔
92

93
        ClassLoader classLoaderOfRealClass = realClass.getClassLoader();
1✔
94
        useClassLoadingBridgeForUpdatingFakeState = ClassLoad.isClassLoaderWithNoDirectAccess(classLoaderOfRealClass);
1✔
95
        inferUseOfClassLoadingBridge(classLoaderOfRealClass, fake);
1✔
96
    }
1✔
97

98
    private void inferUseOfClassLoadingBridge(@Nullable ClassLoader classLoaderOfRealClass, @NonNull Object fake) {
99
        setUseClassLoadingBridge(classLoaderOfRealClass);
1✔
100

101
        if (!useClassLoadingBridge && !isPublic(fake.getClass().getModifiers())) {
1✔
102
            useClassLoadingBridge = true;
1✔
103
        }
104
    }
1✔
105

106
    @Override
107
    public MethodVisitor visitMethod(int access, @NonNull String name, @NonNull String desc, @Nullable String signature,
108
            @Nullable String[] exceptions) {
109
        if ((access & ABSTRACT_OR_SYNTHETIC) != 0) {
1✔
110
            if (isAbstract(access)) {
1✔
111
                // Marks a matching fake method (if any) as having the corresponding faked method.
112
                fakeMethods.findMethod(access, name, desc, signature);
1✔
113
            }
114

115
            return cw.visitMethod(access, name, desc, signature, exceptions);
1✔
116
        }
117

118
        isConstructor = "<init>".equals(name);
1✔
119

120
        if (isConstructor && isFakedSuperclass() || !hasFake(access, name, desc, signature)) {
1✔
121
            return cw.visitMethod(access, name, desc, signature, exceptions);
1✔
122
        }
123

124
        startModifiedMethodVersion(access, name, desc, signature, exceptions);
1✔
125

126
        if (isNative(methodAccess)) {
1✔
127
            generateCodeForInterceptedNativeMethod();
1✔
128
            return methodAnnotationsVisitor;
1✔
129
        }
130

131
        return copyOriginalImplementationWithInjectedInterceptionCode();
1✔
132
    }
133

134
    private boolean hasFake(int access, @NonNull String name, @NonNull String desc, @Nullable String signature) {
135
        String fakeName = getCorrespondingFakeName(name);
1✔
136
        fakeMethod = fakeMethods.findMethod(access, fakeName, desc, signature);
1✔
137
        return fakeMethod != null;
1✔
138
    }
139

140
    @NonNull
141
    private static String getCorrespondingFakeName(@NonNull String name) {
142
        if ("<init>".equals(name)) {
1✔
143
            return "$init";
1✔
144
        }
145

146
        if ("<clinit>".equals(name)) {
1✔
147
            return "$clinit";
1✔
148
        }
149

150
        return name;
1✔
151
    }
152

153
    private boolean isFakedSuperclass() {
154
        return fakedClass != fakeMethods.getRealClass();
1✔
155
    }
156

157
    private void generateCodeForInterceptedNativeMethod() {
158
        generateCallToUpdateFakeState();
1✔
159
        generateCallToFakeMethod();
1✔
160
        generateMethodReturn();
1✔
161
        mw.visitMaxStack(1); // dummy value, real one is calculated by ASM
1✔
162
    }
1✔
163

164
    @Override
165
    protected void generateInterceptionCode() {
166
        Label startOfRealImplementation = null;
1✔
167

168
        if (!isStatic(methodAccess) && !isConstructor && isFakedSuperclass()) {
1✔
169
            Class<?> targetClass = fakeMethods.getRealClass();
1✔
170

171
            if (fakedClass.getClassLoader() == targetClass.getClassLoader()) {
1✔
172
                startOfRealImplementation = new Label();
1✔
173
                mw.visitVarInsn(ALOAD, 0);
1✔
174
                mw.visitTypeInsn(INSTANCEOF, JavaType.getInternalName(targetClass));
1✔
175
                mw.visitJumpInsn(IFEQ, startOfRealImplementation);
1✔
176
            }
177
        }
178

179
        generateCallToUpdateFakeState();
1✔
180

181
        if (isConstructor) {
1✔
182
            generateConditionalCallForFakedConstructor();
1✔
183
        } else {
184
            generateConditionalCallForFakedMethod(startOfRealImplementation);
1✔
185
        }
186
    }
1✔
187

188
    private void generateCallToUpdateFakeState() {
189
        if (useClassLoadingBridgeForUpdatingFakeState) {
1✔
190
            generateCallToControlMethodThroughClassLoadingBridge();
1✔
191
            mw.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
1✔
192
            mw.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
1✔
193
        } else {
194
            mw.visitLdcInsn(fakeMethods.getFakeClassInternalName());
1✔
195
            generateCodeToPassThisOrNullIfStaticMethod();
1✔
196
            mw.visitIntInsn(SIPUSH, fakeMethod.getIndexForFakeState());
1✔
197
            mw.visitMethodInsn(INVOKESTATIC, "mockit/internal/state/TestRun", "updateFakeState",
1✔
198
                    "(Ljava/lang/String;Ljava/lang/Object;I)Z", false);
199
        }
200
    }
1✔
201

202
    private void generateCallToControlMethodThroughClassLoadingBridge() {
203
        generateCodeToObtainInstanceOfClassLoadingBridge(FakeBridge.MB);
1✔
204

205
        // First and second "invoke" arguments:
206
        generateCodeToPassThisOrNullIfStaticMethod();
1✔
207
        mw.visitInsn(ACONST_NULL);
1✔
208

209
        // Create array for call arguments (third "invoke" argument):
210
        generateCodeToCreateArrayOfObject(2);
1✔
211

212
        int i = 0;
1✔
213
        generateCodeToFillArrayElement(i, fakeMethods.getFakeClassInternalName());
1✔
214
        i++;
1✔
215
        generateCodeToFillArrayElement(i, fakeMethod.getIndexForFakeState());
1✔
216

217
        generateCallToInvocationHandler();
1✔
218
    }
1✔
219

220
    private void generateConditionalCallForFakedMethod(@Nullable Label startOfRealImplementation) {
221
        if (startOfRealImplementation == null) {
1✔
222
            // noinspection AssignmentToMethodParameter
223
            startOfRealImplementation = new Label();
1✔
224
        }
225

226
        mw.visitJumpInsn(IFEQ, startOfRealImplementation);
1✔
227
        generateCallToFakeMethod();
1✔
228
        generateMethodReturn();
1✔
229
        mw.visitLabel(startOfRealImplementation);
1✔
230
    }
1✔
231

232
    private void generateConditionalCallForFakedConstructor() {
233
        generateCallToFakeMethod();
1✔
234

235
        int jumpInsnOpcode;
236

237
        if (shouldUseClassLoadingBridge()) {
1✔
238
            mw.visitLdcInsn(VOID_TYPE);
1✔
239
            jumpInsnOpcode = IF_ACMPEQ;
1✔
240
        } else {
241
            jumpInsnOpcode = fakeMethod.hasInvocationParameter() ? IFNE : IFEQ;
1!
242
        }
243

244
        Label startOfRealImplementation = new Label();
1✔
245
        mw.visitJumpInsn(jumpInsnOpcode, startOfRealImplementation);
1✔
246
        mw.visitInsn(RETURN);
1✔
247
        mw.visitLabel(startOfRealImplementation);
1✔
248
    }
1✔
249

250
    /**
251
     * Generates an early fake interception check for constructors that use {@code this()} delegation. The check runs
252
     * before any of the original argument-creation bytecode so that exceptions thrown while building the arguments to
253
     * {@code this()} cannot escape when the fake is active.
254
     * <p>
255
     * When the fake is active the method:
256
     * <ol>
257
     * <li>Initialises {@code this} via the direct superclass's no-argument constructor (which must exist).</li>
258
     * <li>Calls the fake {@code $init} method with the original constructor's parameters.</li>
259
     * <li>Returns immediately, skipping the {@code this()} delegation entirely.</li>
260
     * </ol>
261
     * When the fake is not active (or the superclass has no no-argument constructor) execution falls through to
262
     * {@code originalCodeLabel} and the original constructor body runs normally.
263
     */
264
    @Override
265
    protected void generateEarlyInterceptionCodeForThisDelegationConstructor(@NonNull Label originalCodeLabel) {
266
        if (!superClassHasNoArgConstructor()) {
1!
267
            // Cannot safely initialise 'this' – fall back to post-this() interception only
NEW
268
            mw.visitLabel(originalCodeLabel);
×
NEW
269
            return;
×
270
        }
271

272
        // Check whether the fake is active, passing null for 'this' (which is still uninitialized here)
273
        generateCallToUpdateFakeStateWithNullInstance(); // leaves Z on stack
1✔
274

275
        // If not active, jump to the original constructor body
276
        mw.visitJumpInsn(IFEQ, originalCodeLabel);
1✔
277

278
        // --- Fake-active path ---
279
        // Initialise 'this' via the direct superclass's no-argument constructor so that RETURN is legal
280
        mw.visitVarInsn(ALOAD, 0);
1✔
281
        mw.visitMethodInsn(INVOKESPECIAL, superClassName, "<init>", "()V", false);
1✔
282

283
        // Call the fake $init method (ALOAD_0 is now a properly-initialised reference)
284
        generateCallToFakeMethod();
1✔
285

286
        // If the fake has an Invocation parameter, shouldProceedIntoConstructor() left a Z on the stack.
287
        // Calling the fake with Invocation IS supported (e.g., inv.getInvokedInstance(), inv.getInvocationCount()),
288
        // but inv.proceed() is not: this path has already initialised 'this' via the superclass no-arg constructor
289
        // rather than via the original this() chain, so proceeding would require re-running the original
290
        // argument-creation code. We therefore discard the shouldProceedIntoConstructor() result and always return.
291
        if (fakeMethod.hasInvocationParameter()) {
1✔
292
            mw.visitInsn(POP);
1✔
293
        }
294

295
        mw.visitInsn(RETURN);
1✔
296

297
        // --- Original-code path ---
298
        mw.visitLabel(originalCodeLabel);
1✔
299
    }
1✔
300

301
    /**
302
     * Returns {@code true} when the direct superclass of the faked class declares a no-argument constructor. The result
303
     * determines whether an early fake check can be inserted for {@code this()}-delegation constructors.
304
     */
305
    private boolean superClassHasNoArgConstructor() {
306
        Class<?> superClass = fakedClass.getSuperclass();
1✔
307

308
        // superClass is null only for java.lang.Object itself, which cannot realistically be faked
309
        // with a constructor mock; treat it as "no no-arg constructor" to fall back safely.
310
        if (superClass == null) {
1!
NEW
311
            return false;
×
312
        }
313

314
        try {
315
            superClass.getDeclaredConstructor();
1✔
316
            return true;
1✔
NEW
317
        } catch (NoSuchMethodException e) {
×
NEW
318
            return false;
×
319
        }
320
    }
321

322
    /**
323
     * Like {@link #generateCallToUpdateFakeState()}, but always passes {@code null} as the mocked-instance argument.
324
     * This is used at the very start of a constructor (before {@code super()}/{@code this()} has been called) when
325
     * {@code this} is still an {@code uninitializedThis} reference and cannot legally be passed to a static method.
326
     */
327
    private void generateCallToUpdateFakeStateWithNullInstance() {
328
        if (useClassLoadingBridgeForUpdatingFakeState) {
1!
329
            generateCodeToObtainInstanceOfClassLoadingBridge(FakeBridge.MB);
1✔
330
            mw.visitInsn(ACONST_NULL); // null for 'this' (uninitialized)
1✔
331
            mw.visitInsn(ACONST_NULL);
1✔
332
            generateCodeToCreateArrayOfObject(2);
1✔
333
            int i = 0;
1✔
334
            generateCodeToFillArrayElement(i, fakeMethods.getFakeClassInternalName());
1✔
335
            i++;
1✔
336
            generateCodeToFillArrayElement(i, fakeMethod.getIndexForFakeState());
1✔
337
            generateCallToInvocationHandler();
1✔
338
            mw.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
1✔
339
            mw.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
1✔
340
        } else {
1✔
NEW
341
            mw.visitLdcInsn(fakeMethods.getFakeClassInternalName());
×
NEW
342
            mw.visitInsn(ACONST_NULL); // null for 'this' (uninitialized)
×
NEW
343
            mw.visitIntInsn(SIPUSH, fakeMethod.getIndexForFakeState());
×
NEW
344
            mw.visitMethodInsn(INVOKESTATIC, "mockit/internal/state/TestRun", "updateFakeState",
×
345
                    "(Ljava/lang/String;Ljava/lang/Object;I)Z", false);
346
        }
347
    }
1✔
348

349
    private void generateCallToFakeMethod() {
350
        if (shouldUseClassLoadingBridge()) {
1✔
351
            generateCallToFakeMethodThroughClassLoadingBridge();
1✔
352
        } else {
353
            generateDirectCallToFakeMethod();
1✔
354
        }
355
    }
1✔
356

357
    private boolean shouldUseClassLoadingBridge() {
358
        return useClassLoadingBridge || !fakeMethod.isPublic();
1✔
359
    }
360

361
    private void generateCallToFakeMethodThroughClassLoadingBridge() {
362
        generateCodeToObtainInstanceOfClassLoadingBridge(FakeMethodBridge.MB);
1✔
363

364
        // First and second "invoke" arguments:
365
        boolean isStatic = generateCodeToPassThisOrNullIfStaticMethod();
1✔
366
        mw.visitInsn(ACONST_NULL);
1✔
367

368
        // Create array for call arguments (third "invoke" argument):
369
        JavaType[] argTypes = JavaType.getArgumentTypes(methodDesc);
1✔
370
        generateCodeToCreateArrayOfObject(6 + argTypes.length);
1✔
371

372
        int i = 0;
1✔
373
        generateCodeToFillArrayElement(i, fakeMethods.getFakeClassInternalName());
1✔
374
        i++;
1✔
375
        generateCodeToFillArrayElement(i, classDesc);
1✔
376
        i++;
1✔
377
        generateCodeToFillArrayElement(i, methodAccess);
1✔
378
        i++;
1✔
379

380
        if (fakeMethod.hasInvocationParameterOnly()) {
1✔
381
            generateCodeToFillArrayElement(i, methodName);
1✔
382
            i++;
1✔
383
            generateCodeToFillArrayElement(i, methodDesc);
1✔
384
        } else {
385
            generateCodeToFillArrayElement(i, fakeMethod.name);
1✔
386
            i++;
1✔
387
            generateCodeToFillArrayElement(i, fakeMethod.desc);
1✔
388
        }
389
        i++;
1✔
390

391
        generateCodeToFillArrayElement(i, fakeMethod.getIndexForFakeState());
1✔
392
        i++;
1✔
393

394
        generateCodeToFillArrayWithParameterValues(argTypes, i, isStatic ? 0 : 1);
1✔
395
        generateCallToInvocationHandler();
1✔
396
    }
1✔
397

398
    private void generateDirectCallToFakeMethod() {
399
        String fakeClassDesc = fakeMethods.getFakeClassInternalName();
1✔
400
        int invokeOpcode;
401

402
        if (fakeMethod.isStatic()) {
1✔
403
            invokeOpcode = INVOKESTATIC;
1✔
404
        } else {
405
            generateCodeToObtainFakeInstance(fakeClassDesc);
1✔
406
            invokeOpcode = INVOKEVIRTUAL;
1✔
407
        }
408

409
        boolean canProceedIntoConstructor = generateArgumentsForFakeMethodInvocation();
1✔
410
        mw.visitMethodInsn(invokeOpcode, fakeClassDesc, fakeMethod.name, fakeMethod.desc, false);
1✔
411

412
        if (canProceedIntoConstructor) {
1✔
413
            mw.visitMethodInsn(INVOKEVIRTUAL, "mockit/internal/faking/FakeInvocation", "shouldProceedIntoConstructor",
1✔
414
                    "()Z", false);
415
        }
416
    }
1✔
417

418
    private void generateCodeToObtainFakeInstance(@NonNull String fakeClassDesc) {
419
        mw.visitLdcInsn(fakeClassDesc);
1✔
420
        generateCodeToPassThisOrNullIfStaticMethod();
1✔
421
        mw.visitMethodInsn(INVOKESTATIC, "mockit/internal/state/TestRun", "getFake",
1✔
422
                "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", false);
423
        mw.visitTypeInsn(CHECKCAST, fakeClassDesc);
1✔
424
    }
1✔
425

426
    private boolean generateArgumentsForFakeMethodInvocation() {
427
        String fakedDesc = fakeMethod.hasInvocationParameterOnly() ? methodDesc
1✔
428
                : fakeMethod.fakeDescWithoutInvocationParameter;
1✔
429
        JavaType[] argTypes = JavaType.getArgumentTypes(fakedDesc);
1✔
430
        int varIndex = isStatic(methodAccess) ? 0 : 1;
1✔
431
        boolean canProceedIntoConstructor = false;
1✔
432

433
        if (fakeMethod.hasInvocationParameter()) {
1✔
434
            generateCallToCreateNewFakeInvocation(argTypes, varIndex);
1✔
435

436
            // When invoking a constructor, the invocation object will need to be consulted for proceeding:
437
            if (isConstructor) {
1✔
438
                mw.visitInsn(fakeMethod.isStatic() ? DUP : DUP_X1);
1!
439
                canProceedIntoConstructor = true;
1✔
440
            }
441
        }
442

443
        if (!fakeMethod.hasInvocationParameterOnly()) {
1✔
444
            passArgumentsForFakeMethodCall(argTypes, varIndex);
1✔
445
        }
446

447
        return canProceedIntoConstructor;
1✔
448
    }
449

450
    private void generateCallToCreateNewFakeInvocation(@NonNull JavaType[] argTypes,
451
            @NonNegative int initialParameterIndex) {
452
        generateCodeToPassThisOrNullIfStaticMethod();
1✔
453

454
        int argCount = argTypes.length;
1✔
455

456
        if (argCount == 0) {
1✔
457
            mw.visitInsn(ACONST_NULL);
1✔
458
        } else {
459
            generateCodeToCreateArrayOfObject(argCount);
1✔
460
            generateCodeToFillArrayWithParameterValues(argTypes, 0, initialParameterIndex);
1✔
461
        }
462

463
        mw.visitLdcInsn(fakeMethods.getFakeClassInternalName());
1✔
464
        mw.visitIntInsn(SIPUSH, fakeMethod.getIndexForFakeState());
1✔
465
        mw.visitLdcInsn(classDesc);
1✔
466
        mw.visitLdcInsn(methodName);
1✔
467
        mw.visitLdcInsn(methodDesc);
1✔
468

469
        mw.visitMethodInsn(INVOKESTATIC, "mockit/internal/faking/FakeInvocation", "create",
1✔
470
                "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)"
471
                        + "Lmockit/internal/faking/FakeInvocation;",
472
                false);
473
    }
1✔
474

475
    private void passArgumentsForFakeMethodCall(@NonNull JavaType[] argTypes, @NonNegative int varIndex) {
476
        boolean forGenericMethod = fakeMethod.isForGenericMethod();
1✔
477

478
        for (JavaType argType : argTypes) {
1✔
479
            int opcode = argType.getOpcode(ILOAD);
1✔
480
            mw.visitVarInsn(opcode, varIndex);
1✔
481

482
            if (forGenericMethod && argType instanceof ReferenceType) {
1!
483
                String typeDesc = ((ReferenceType) argType).getInternalName();
1✔
484
                mw.visitTypeInsn(CHECKCAST, typeDesc);
1✔
485
            }
486

487
            varIndex += argType.getSize();
1✔
488
        }
489
    }
1✔
490

491
    private void generateMethodReturn() {
492
        if (shouldUseClassLoadingBridge() || fakeMethod.isAdvice) {
1✔
493
            generateReturnWithObjectAtTopOfTheStack(methodDesc);
1✔
494
        } else {
495
            JavaType returnType = JavaType.getReturnType(methodDesc);
1✔
496
            mw.visitInsn(returnType.getOpcode(IRETURN));
1✔
497
        }
498
    }
1✔
499
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc