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

hazendaz / jmockit1 / 496

15 Nov 2025 05:33PM UTC coverage: 72.192% (-0.008%) from 72.2%
496

push

github

web-flow
Merge pull request #412 from hazendaz/renovate/major-spring-core

Update spring core to v7 (major)

5677 of 8360 branches covered (67.91%)

Branch coverage included in aggregate %.

11922 of 16018 relevant lines covered (74.43%)

0.74 hits per line

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

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

8
import static mockit.asm.jvmConstants.Opcodes.DLOAD;
9
import static mockit.asm.jvmConstants.Opcodes.DSTORE;
10
import static mockit.asm.jvmConstants.Opcodes.GOTO;
11
import static mockit.asm.jvmConstants.Opcodes.GOTO_W;
12
import static mockit.asm.jvmConstants.Opcodes.IINC;
13
import static mockit.asm.jvmConstants.Opcodes.ILOAD;
14
import static mockit.asm.jvmConstants.Opcodes.INVOKEDYNAMIC;
15
import static mockit.asm.jvmConstants.Opcodes.INVOKEINTERFACE;
16
import static mockit.asm.jvmConstants.Opcodes.ISTORE;
17
import static mockit.asm.jvmConstants.Opcodes.LDC;
18
import static mockit.asm.jvmConstants.Opcodes.LDC2_W;
19
import static mockit.asm.jvmConstants.Opcodes.LDC_W;
20
import static mockit.asm.jvmConstants.Opcodes.LLOAD;
21
import static mockit.asm.jvmConstants.Opcodes.LOOKUPSWITCH;
22
import static mockit.asm.jvmConstants.Opcodes.LSTORE;
23
import static mockit.asm.jvmConstants.Opcodes.MULTIANEWARRAY;
24
import static mockit.asm.jvmConstants.Opcodes.SIPUSH;
25
import static mockit.asm.jvmConstants.Opcodes.TABLESWITCH;
26
import static mockit.asm.jvmConstants.Opcodes.WIDE;
27

28
import edu.umd.cs.findbugs.annotations.NonNull;
29
import edu.umd.cs.findbugs.annotations.Nullable;
30

31
import mockit.asm.SignatureWriter;
32
import mockit.asm.annotations.AnnotationVisitor;
33
import mockit.asm.classes.ClassWriter;
34
import mockit.asm.constantPool.ClassMemberItem;
35
import mockit.asm.constantPool.DynamicItem;
36
import mockit.asm.constantPool.Item;
37
import mockit.asm.constantPool.LongValueItem;
38
import mockit.asm.constantPool.StringItem;
39
import mockit.asm.controlFlow.CFGAnalysis;
40
import mockit.asm.controlFlow.Frame;
41
import mockit.asm.controlFlow.Label;
42
import mockit.asm.controlFlow.StackMapTableWriter;
43
import mockit.asm.exceptionHandling.ExceptionHandling;
44
import mockit.asm.jvmConstants.Access;
45
import mockit.asm.jvmConstants.Opcodes;
46
import mockit.asm.types.JavaType;
47
import mockit.asm.util.ByteVector;
48
import mockit.asm.util.MethodHandle;
49

50
import org.checkerframework.checker.index.qual.NonNegative;
51

52
/**
53
 * A {@link MethodVisitor} that generates methods in bytecode form. Each visit method of this class appends the bytecode
54
 * corresponding to the visited instruction to a byte vector, in the order these methods are called.
55
 */
56
@SuppressWarnings({ "OverlyCoupledClass", "ClassWithTooManyFields", "OverlyComplexClass" })
57
public final class MethodWriter extends MethodVisitor {
58
    /**
59
     * The class writer to which this method must be added.
60
     */
61
    @NonNull
62
    public final ClassWriter cw;
63

64
    /**
65
     * The index of the constant pool item that contains the name of this method.
66
     */
67
    private final int nameItemIndex;
68

69
    /**
70
     * The index of the constant pool item that contains the descriptor of this method.
71
     */
72
    private final int descItemIndex;
73

74
    /**
75
     * The descriptor of this method.
76
     */
77
    @NonNull
78
    private final String descriptor;
79

80
    @Nullable
81
    private final SignatureWriter signatureWriter;
82

83
    /**
84
     * If not zero, indicates that the code of this method must be copied from <code>cw.code</code>. More precisely,
85
     * this field gives the index of the first byte to be copied from <code>cw.code</code>.
86
     */
87
    @NonNegative
88
    int classReaderOffset;
89

90
    /**
91
     * If not zero, indicates that the code of this method must be copied from <code>cw.cr</code>. More precisely, this
92
     * field gives the number of bytes to be copied from <code>cw.code</code>.
93
     */
94
    @NonNegative
95
    int classReaderLength;
96

97
    @Nullable
98
    private final ExceptionsWriter exceptionsWriter;
99

100
    /**
101
     * The runtime visible parameter annotations of this method, if any.
102
     */
103
    @Nullable
104
    private AnnotationVisitor[] parameterAnnotations;
105

106
    /**
107
     * The bytecode of this method.
108
     */
109
    @NonNull
110
    private final ByteVector code;
111

112
    @NonNull
113
    private final ExceptionHandling exceptionHandling;
114
    @NonNull
115
    private final StackMapTableWriter stackMapTableWriter;
116
    @NonNull
117
    private final LocalVariableTableWriter localVariableTableWriter;
118
    @NonNull
119
    private final LineNumberTableWriter lineNumberTableWriter;
120
    @NonNull
121
    private final CFGAnalysis cfgAnalysis;
122

123
    private final boolean computeFrames;
124

125
    /**
126
     * Initializes this MethodWriter.
127
     *
128
     * @param cw
129
     *            the class writer in which the method must be added
130
     * @param access
131
     *            the method's access flags (see {@link Opcodes})
132
     * @param name
133
     *            the method's name
134
     * @param desc
135
     *            the method's descriptor (see {@link JavaType})
136
     * @param signature
137
     *            the method's signature
138
     * @param exceptions
139
     *            the internal names of the method's exceptions
140
     * @param computeFrames
141
     *            <code>true</code> if the stack map tables must be recomputed from scratch
142
     */
143
    public MethodWriter(@NonNull ClassWriter cw, int access, @NonNull String name, @NonNull String desc,
144
            @Nullable String signature, @Nullable String[] exceptions, boolean computeFrames) {
145
        super(cw.getConstantPoolGeneration(), "<init>".equals(name) ? access | Access.CONSTRUCTOR : access);
1✔
146
        this.cw = cw;
1✔
147
        nameItemIndex = cp.newUTF8(name);
1✔
148
        descItemIndex = cp.newUTF8(desc);
1✔
149
        descriptor = desc;
1✔
150
        signatureWriter = signature == null ? null : new SignatureWriter(cp, signature);
1✔
151
        exceptionsWriter = exceptions == null ? null : new ExceptionsWriter(cp, exceptions);
1✔
152
        code = new ByteVector();
1✔
153
        this.computeFrames = computeFrames;
1✔
154
        exceptionHandling = new ExceptionHandling(cp);
1✔
155
        stackMapTableWriter = new StackMapTableWriter(cp, cw.isJava6OrNewer(), access, desc);
1✔
156
        localVariableTableWriter = new LocalVariableTableWriter(cp);
1✔
157
        lineNumberTableWriter = new LineNumberTableWriter(cp);
1✔
158
        cfgAnalysis = new CFGAnalysis(cp, cw.getInternalClassName(), code, computeFrames);
1✔
159

160
        createMarkerAttributes(cw.getClassVersion());
1✔
161
    }
1✔
162

163
    @NonNull
164
    @Override
165
    public AnnotationVisitor visitParameterAnnotation(@NonNegative int parameter, @NonNull String desc) {
166
        AnnotationVisitor aw = new AnnotationVisitor(cp, desc);
1✔
167

168
        if (parameterAnnotations == null) {
1!
169
            int numParameters = JavaType.getArgumentTypes(descriptor).length;
1✔
170
            parameterAnnotations = new AnnotationVisitor[numParameters];
1✔
171
        }
172

173
        aw.setNext(parameterAnnotations[parameter]);
1✔
174
        parameterAnnotations[parameter] = aw;
1✔
175

176
        return aw;
1✔
177
    }
178

179
    @Override
180
    public void visitInsn(int opcode) {
181
        // Adds the instruction to the bytecode of the method.
182
        code.putByte(opcode);
1✔
183

184
        cfgAnalysis.updateCurrentBlockForZeroOperandInstruction(opcode);
1✔
185
    }
1✔
186

187
    @Override
188
    public void visitIntInsn(int opcode, int operand) {
189
        cfgAnalysis.updateCurrentBlockForSingleIntOperandInstruction(opcode, operand);
1✔
190

191
        // Adds the instruction to the bytecode of the method.
192
        if (opcode == SIPUSH) {
1✔
193
            code.put12(SIPUSH, operand);
1✔
194
        } else { // BIPUSH or NEWARRAY
195
            code.put11(opcode, operand);
1✔
196
        }
197
    }
1✔
198

199
    @Override
200
    public void visitVarInsn(int opcode, @NonNegative int varIndex) {
201
        cfgAnalysis.updateCurrentBlockForLocalVariableInstruction(opcode, varIndex);
1✔
202

203
        updateMaxLocals(opcode, varIndex);
1✔
204

205
        // Adds the instruction to the bytecode of the method.
206
        if (varIndex < 4) {
1✔
207
            int opt;
208

209
            if (opcode < ISTORE) { // ILOAD_0
1✔
210
                opt = 26 + (opcode - ILOAD << 2) + varIndex;
1✔
211
            } else { // ISTORE_0
212
                opt = 59 + (opcode - ISTORE << 2) + varIndex;
1✔
213
            }
214

215
            code.putByte(opt);
1✔
216
        } else if (varIndex >= 256) {
1!
217
            code.putByte(WIDE).put12(opcode, varIndex);
×
218
        } else {
219
            code.put11(opcode, varIndex);
1✔
220
        }
221

222
        if (opcode >= ISTORE && computeFrames && exceptionHandling.hasHandlers()) {
1✔
223
            visitLabel(new Label());
1✔
224
        }
225
    }
1✔
226

227
    private void updateMaxLocals(int opcode, @NonNegative int varIndex) {
228
        int n = opcode == LLOAD || opcode == DLOAD || opcode == LSTORE || opcode == DSTORE ? varIndex + 2
1✔
229
                : varIndex + 1;
1✔
230
        stackMapTableWriter.updateMaxLocals(n);
1✔
231
    }
1✔
232

233
    @Override
234
    public void visitTypeInsn(int opcode, @NonNull String typeDesc) {
235
        StringItem typeItem = cp.newClassItem(typeDesc);
1✔
236
        cfgAnalysis.updateCurrentBlockForTypeInstruction(opcode, typeItem);
1✔
237

238
        // Adds the instruction to the bytecode of the method.
239
        code.put12(opcode, typeItem.index);
1✔
240
    }
1✔
241

242
    @Override
243
    public void visitFieldInsn(int opcode, @NonNull String owner, @NonNull String name, @NonNull String desc) {
244
        ClassMemberItem fieldItem = cp.newFieldItem(owner, name, desc);
1✔
245
        cfgAnalysis.updateCurrentBlockForFieldInstruction(opcode, fieldItem, desc);
1✔
246

247
        // Adds the instruction to the bytecode of the method.
248
        code.put12(opcode, fieldItem.index);
1✔
249
    }
1✔
250

251
    @Override
252
    public void visitMethodInsn(int opcode, @NonNull String owner, @NonNull String name, @NonNull String desc,
253
            boolean itf) {
254
        ClassMemberItem invokeItem = cp.newMethodItem(owner, name, desc, itf);
1✔
255
        cfgAnalysis.updateCurrentBlockForInvokeInstruction(invokeItem, opcode, desc);
1✔
256

257
        // Adds the instruction to the bytecode of the method.
258
        code.put12(opcode, invokeItem.index);
1✔
259

260
        if (opcode == INVOKEINTERFACE) {
1✔
261
            int argSize = invokeItem.getArgSizeComputingIfNeeded(desc);
1✔
262
            code.put11(argSize >> 2, 0);
1✔
263
        }
264
    }
1✔
265

266
    @Override
267
    public void visitInvokeDynamicInsn(@NonNull String name, @NonNull String desc, @NonNull MethodHandle bsm,
268
            @NonNull Object... bsmArgs) {
269
        DynamicItem invokeItem = cw.addInvokeDynamicReference(name, desc, bsm, bsmArgs);
1✔
270
        cfgAnalysis.updateCurrentBlockForInvokeInstruction(invokeItem, INVOKEDYNAMIC, desc);
1✔
271

272
        // Adds the instruction to the bytecode of the method.
273
        code.put12(INVOKEDYNAMIC, invokeItem.index);
1✔
274
        code.putShort(0);
1✔
275
    }
1✔
276

277
    @Override
278
    public void visitJumpInsn(int opcode, @NonNull Label label) {
279
        Label nextInsn = cfgAnalysis.updateCurrentBlockForJumpInstruction(opcode, label);
1✔
280

281
        // Adds the instruction to the bytecode of the method.
282
        if (label.isResolved() && label.position - code.getLength() < Short.MIN_VALUE) {
1!
283
            // Case of a backward jump with an offset < -32768. In this case we automatically replace GOTO with GOTO_W
284
            // and IFxxx <l> with
285
            // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and
286
            // where <l'> designates the
287
            // instruction just after the GOTO_W.
288
            if (opcode != GOTO) {
×
289
                // If the IF instruction is transformed into IFNOT GOTO_W the next instruction becomes the target of the
290
                // IFNOT instruction.
291
                if (nextInsn != null) {
×
292
                    nextInsn.markAsTarget();
×
293
                }
294

295
                code.putByte(opcode <= 166 ? (opcode + 1 ^ 1) - 1 : opcode ^ 1);
×
296
                code.putShort(8); // jump offset
×
297
            }
298

299
            code.putByte(GOTO_W);
×
300
            label.put(code, code.getLength() - 1, true);
×
301
        } else {
302
            // Case of a backward jump with an offset >= -32768, or of a forward jump with, of course, an unknown
303
            // offset.
304
            // In these cases we store the offset in 2 bytes (which will be increased in resizeInstructions, if needed).
305
            code.putByte(opcode);
1✔
306
            label.put(code, code.getLength() - 1, false);
1✔
307
        }
308

309
        cfgAnalysis.updateCurrentBlockForJumpTarget(opcode, nextInsn);
1✔
310
    }
1✔
311

312
    @Override
313
    public void visitLabel(@NonNull Label label) {
314
        cfgAnalysis.updateCurrentBlockForLabelBeforeNextInstruction(label);
1✔
315
    }
1✔
316

317
    @Override
318
    public void visitLdcInsn(@NonNull Object cst) {
319
        Item constItem = cp.newConstItem(cst);
1✔
320
        cfgAnalysis.updateCurrentBlockForLDCInstruction(constItem);
1✔
321

322
        // Adds the instruction to the bytecode of the method.
323
        int index = constItem.index;
1✔
324

325
        if (constItem instanceof LongValueItem) {
1✔
326
            code.put12(LDC2_W, index);
1✔
327
        } else if (index >= 256) {
1✔
328
            code.put12(LDC_W, index);
1✔
329
        } else {
330
            code.put11(LDC, index);
1✔
331
        }
332
    }
1✔
333

334
    @Override
335
    public void visitIincInsn(@NonNegative int varIndex, int increment) {
336
        cfgAnalysis.updateCurrentBlockForIINCInstruction(varIndex);
1✔
337

338
        // Updates max locals.
339
        int n = varIndex + 1;
1✔
340
        stackMapTableWriter.updateMaxLocals(n);
1✔
341

342
        // Adds the instruction to the bytecode of the method.
343
        if (varIndex > 255 || increment > 127 || increment < -128) {
1!
344
            code.putByte(WIDE).put12(IINC, varIndex).putShort(increment);
×
345
        } else {
346
            code.putByte(IINC).put11(varIndex, increment);
1✔
347
        }
348
    }
1✔
349

350
    @Override
351
    public void visitTableSwitchInsn(int min, int max, @NonNull Label dflt, @NonNull Label... labels) {
352
        // Adds the instruction to the bytecode of the method.
353
        int source = code.getLength();
1✔
354
        code.putByte(TABLESWITCH);
1✔
355
        code.roundUpLength();
1✔
356
        dflt.put(code, source, true);
1✔
357
        code.putInt(min).putInt(max);
1✔
358

359
        for (Label label : labels) {
1✔
360
            label.put(code, source, true);
1✔
361
        }
362

363
        cfgAnalysis.updateCurrentBlockForSwitchInstruction(dflt, labels);
1✔
364
    }
1✔
365

366
    @Override
367
    public void visitLookupSwitchInsn(@NonNull Label dflt, @NonNull int[] keys, @NonNull Label[] labels) {
368
        // Adds the instruction to the bytecode of the method.
369
        int source = code.getLength();
1✔
370
        code.putByte(LOOKUPSWITCH);
1✔
371
        code.roundUpLength();
1✔
372
        dflt.put(code, source, true);
1✔
373
        code.putInt(labels.length);
1✔
374

375
        for (int i = 0; i < labels.length; i++) {
1✔
376
            code.putInt(keys[i]);
1✔
377
            labels[i].put(code, source, true);
1✔
378
        }
379

380
        cfgAnalysis.updateCurrentBlockForSwitchInstruction(dflt, labels);
1✔
381
    }
1✔
382

383
    @Override
384
    public void visitMultiANewArrayInsn(@NonNull String desc, @NonNegative int dims) {
385
        StringItem arrayTypeItem = cp.newClassItem(desc);
1✔
386
        cfgAnalysis.updateCurrentBlockForMULTIANEWARRAYInstruction(arrayTypeItem, dims);
1✔
387

388
        // Adds the instruction to the bytecode of the method.
389
        code.put12(MULTIANEWARRAY, arrayTypeItem.index).putByte(dims);
1✔
390
    }
1✔
391

392
    @Override
393
    public void visitTryCatchBlock(@NonNull Label start, @NonNull Label end, @NonNull Label handler,
394
            @Nullable String type) {
395
        exceptionHandling.addHandler(start, end, handler, type);
1✔
396
    }
1✔
397

398
    @Override
399
    public void visitLocalVariable(@NonNull String name, @NonNull String desc, @Nullable String signature,
400
            @NonNull Label start, @NonNull Label end, @NonNegative int index) {
401
        int localsCount = localVariableTableWriter.addLocalVariable(name, desc, signature, start, end, index);
1✔
402
        stackMapTableWriter.updateMaxLocals(localsCount);
1✔
403
    }
1✔
404

405
    @Override
406
    public void visitLineNumber(@NonNegative int line, @NonNull Label start) {
407
        lineNumberTableWriter.addLineNumber(line, start);
1✔
408
    }
1✔
409

410
    @Override
411
    public void visitMaxStack(@NonNegative int maxStack) {
412
        int computedMaxStack;
413

414
        if (computeFrames) {
1✔
415
            exceptionHandling.completeControlFlowGraphWithExceptionHandlerBlocksFromComputedFrames();
1✔
416

417
            Frame firstFrame = cfgAnalysis.getFirstFrame();
1✔
418
            stackMapTableWriter.createAndVisitFirstFrame(firstFrame, cw.getInternalClassName(), descriptor,
1✔
419
                    classOrMemberAccess);
420

421
            computedMaxStack = cfgAnalysis.computeMaxStackSizeFromComputedFrames();
1✔
422
            visitAllFramesToBeStoredInStackMap();
1✔
423
        } else {
1✔
424
            // TODO: figure out if/when the next call is needed, since no tests fail if commented out
425
            exceptionHandling.completeControlFlowGraphWithExceptionHandlerBlocks();
1✔
426

427
            computedMaxStack = cfgAnalysis.computeMaxStackSize();
1✔
428
            computedMaxStack = Math.max(maxStack, computedMaxStack);
1✔
429
        }
430

431
        stackMapTableWriter.setMaxStack(computedMaxStack);
1✔
432
    }
1✔
433

434
    private void visitAllFramesToBeStoredInStackMap() {
435
        Label label = cfgAnalysis.getLabelForFirstBasicBlock();
1✔
436

437
        while (label != null) {
1✔
438
            Frame frame = label.getFrame();
1✔
439

440
            if (label.isStoringFrame()) {
1✔
441
                stackMapTableWriter.visitFrame(frame);
1✔
442
            }
443

444
            label = label.getSuccessor();
1✔
445
        }
1✔
446
    }
1✔
447

448
    /**
449
     * Returns the size of the bytecode of this method.
450
     */
451
    @NonNegative
452
    public int getSize() {
453
        if (classReaderOffset > 0) {
1✔
454
            return 6 + classReaderLength;
1✔
455
        }
456

457
        int size = 8 + getMarkerAttributesSize() + getAnnotationsSize() + getParameterAnnotationsSize();
1✔
458
        int codeLength = code.getLength();
1✔
459

460
        if (codeLength > 0) {
1!
461
            if (codeLength > 65536) {
1!
462
                throw new RuntimeException("Method code too large!");
×
463
            }
464

465
            cp.newUTF8("Code");
1✔
466

467
            size += 18 + codeLength + exceptionHandling.getSize();
1✔
468
            size += localVariableTableWriter.getSize();
1✔
469
            size += lineNumberTableWriter.getSize();
1✔
470
            size += stackMapTableWriter.getSize();
1✔
471
        }
472

473
        if (exceptionsWriter != null) {
1✔
474
            size += exceptionsWriter.getSize();
1✔
475
        }
476

477
        if (signatureWriter != null) {
1✔
478
            size += signatureWriter.getSize();
1✔
479
        }
480

481
        return size;
1✔
482
    }
483

484
    @NonNegative
485
    private int getParameterAnnotationsSize() {
486
        int size = 0;
1✔
487

488
        if (parameterAnnotations != null) {
1✔
489
            cp.newUTF8("RuntimeVisibleParameterAnnotations");
1✔
490

491
            int n = parameterAnnotations.length;
1✔
492
            size += 7 + 2 * n;
1✔
493

494
            for (int i = n - 1; i >= 0; i--) {
1✔
495
                AnnotationVisitor parameterAnnotation = parameterAnnotations[i];
1✔
496
                size += parameterAnnotation == null ? 0 : parameterAnnotation.getSize();
1✔
497
            }
498
        }
499

500
        return size;
1✔
501
    }
502

503
    /**
504
     * Puts the bytecode of this method in the given byte vector.
505
     */
506
    @Override
507
    protected void put(@NonNull ByteVector out) {
508
        putAccess(out, Access.CONSTRUCTOR);
1✔
509
        out.putShort(nameItemIndex);
1✔
510
        out.putShort(descItemIndex);
1✔
511

512
        if (classReaderOffset > 0) {
1✔
513
            out.putByteArray(cw.code, classReaderOffset, classReaderLength);
1✔
514
            return;
1✔
515
        }
516

517
        putMethodAttributeCount(out);
1✔
518
        putMethodCode(out);
1✔
519

520
        if (exceptionsWriter != null) {
1✔
521
            exceptionsWriter.put(out);
1✔
522
        }
523

524
        putMarkerAttributes(out);
1✔
525

526
        if (signatureWriter != null) {
1✔
527
            signatureWriter.put(out);
1✔
528
        }
529

530
        putAnnotationAttributes(out);
1✔
531
    }
1✔
532

533
    private void putMethodAttributeCount(@NonNull ByteVector out) {
534
        int attributeCount = getMarkerAttributeCount();
1✔
535

536
        if (code.getLength() > 0) {
1!
537
            attributeCount++;
1✔
538
        }
539

540
        if (exceptionsWriter != null) {
1✔
541
            attributeCount++;
1✔
542
        }
543

544
        if (signatureWriter != null) {
1✔
545
            attributeCount++;
1✔
546
        }
547

548
        if (annotations != null) {
1✔
549
            attributeCount++;
1✔
550
        }
551

552
        if (parameterAnnotations != null) {
1✔
553
            attributeCount++;
1✔
554
        }
555

556
        out.putShort(attributeCount);
1✔
557
    }
1✔
558

559
    private void putMethodCode(@NonNull ByteVector out) {
560
        if (code.getLength() > 0) {
1!
561
            putCodeSize(out);
1✔
562
            stackMapTableWriter.putMaxStackAndLocals(out);
1✔
563
            out.putInt(code.getLength()).putByteVector(code);
1✔
564
            exceptionHandling.put(out);
1✔
565

566
            int codeAttributeCount = localVariableTableWriter.getAttributeCount();
1✔
567

568
            if (lineNumberTableWriter.hasLineNumbers()) {
1✔
569
                codeAttributeCount++;
1✔
570
            }
571

572
            if (stackMapTableWriter.hasStackMap()) {
1✔
573
                codeAttributeCount++;
1✔
574
            }
575

576
            out.putShort(codeAttributeCount);
1✔
577
            localVariableTableWriter.put(out);
1✔
578
            lineNumberTableWriter.put(out);
1✔
579
            stackMapTableWriter.put(out);
1✔
580
        }
581
    }
1✔
582

583
    private void putCodeSize(@NonNull ByteVector out) {
584
        int size = 12 + code.getLength() + exceptionHandling.getSize() + localVariableTableWriter.getSize()
1✔
585
                + lineNumberTableWriter.getSize() + stackMapTableWriter.getSize();
1✔
586

587
        out.putShort(cp.newUTF8("Code")).putInt(size);
1✔
588
    }
1✔
589

590
    private void putAnnotationAttributes(@NonNull ByteVector out) {
591
        putAnnotations(out);
1✔
592

593
        if (parameterAnnotations != null) {
1✔
594
            out.putShort(cp.newUTF8("RuntimeVisibleParameterAnnotations"));
1✔
595
            AnnotationVisitor.put(out, parameterAnnotations);
1✔
596
        }
597
    }
1✔
598

599
    @Nullable
600
    public Label getCurrentBlock() {
601
        return cfgAnalysis.getLabelForCurrentBasicBlock();
×
602
    }
603
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc