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

hazendaz / jmockit1 / 876

24 May 2026 05:47PM UTC coverage: 75.471% (-0.03%) from 75.496%
876

Pull #512

github

web-flow
Merge ffde9bbb6 into 19f6c4a1f
Pull Request #512: Modernize flagged collection/reflection API usages in `main` module (Java 21 build path)

6026 of 8488 branches covered (70.99%)

Branch coverage included in aggregate %.

25 of 34 new or added lines in 15 files covered. (73.53%)

5 existing lines in 1 file now uncovered.

12659 of 16270 relevant lines covered (77.81%)

0.78 hits per line

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

96.41
/main/src/main/java/mockit/asm/metadata/ClassMetadataReader.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.metadata;
7

8
import edu.umd.cs.findbugs.annotations.NonNull;
9
import edu.umd.cs.findbugs.annotations.Nullable;
10

11
import java.nio.charset.Charset;
12
import java.util.ArrayList;
13
import java.util.EnumSet;
14
import java.util.List;
15

16
import mockit.asm.jvmConstants.Access;
17

18
import org.checkerframework.checker.index.qual.NonNegative;
19

20
public final class ClassMetadataReader extends ObjectWithAttributes {
21
    private static final Charset UTF8 = Charset.forName("UTF-8");
1✔
22
    private static final ConstantPoolTag[] CONSTANT_POOL_TAGS = ConstantPoolTag.values();
1✔
23

24
    enum ConstantPoolTag { // values from JVM spec Table 4.4.A
1✔
25
        No0, // 0
1✔
26
        Utf8(2), // 1 (has variable size)
1✔
27
        No2, // 2
1✔
28
        Integer(4), // 3
1✔
29
        Float(4), // 4
1✔
30
        Long(8), // 5
1✔
31
        Double(8), // 6
1✔
32
        Class(2), // 7
1✔
33
        String(2), // 8
1✔
34
        FieldRef(4), // 9
1✔
35
        MethodRef(4), // 10
1✔
36
        InterfaceMethodRef(4), // 11
1✔
37
        NameAndType(4), // 12
1✔
38
        No13, No14, MethodHandle(3), // 15, added in Java 7
1✔
39
        MethodType(2), // 16, added in Java 7
1✔
40
        ConstantDynamic(4), // 17, added in Java 11
1✔
41
        InvokeDynamic(4), // 18, added in Java 7
1✔
42
        Module(2), // 19, added in Java 9
1✔
43
        Package(2); // 20, added in Java 9
1✔
44

45
        @NonNegative
46
        final int itemSize;
47

48
        ConstantPoolTag() {
1✔
49
            itemSize = 0;
1✔
50
        }
1✔
51

52
        ConstantPoolTag(@NonNegative int itemSize) {
1✔
53
            this.itemSize = itemSize;
1✔
54
        }
1✔
55
    }
56

57
    public enum Attribute {
1✔
58
        Annotations, Parameters, Signature
1✔
59
    }
60

61
    @NonNull
62
    private final byte[] code;
63
    @NonNull
64
    private final int[] cpItemCodeIndexes;
65
    @Nullable
66
    private final EnumSet<Attribute> attributesToRead;
67

68
    /**
69
     * The constant pool starts at index 10 in the code array; this is the end index, which must be computed as it's not
70
     * stored anywhere.
71
     */
72
    @NonNegative
73
    private final int cpEndIndex;
74

75
    @NonNegative
76
    private int fieldsEndIndex;
77
    @NonNegative
78
    private int methodsEndIndex;
79

80
    @NonNegative
81
    public static int readVersion(@NonNull byte[] code) {
82
        int byte0 = (code[4] & 0xFF) << 24;
1✔
83
        int byte1 = (code[5] & 0xFF) << 16;
1✔
84
        int byte2 = (code[6] & 0xFF) << 8;
1✔
85
        int byte3 = code[7] & 0xFF;
1✔
86
        return byte0 | byte1 | byte2 | byte3;
1✔
87
    }
88

89
    public ClassMetadataReader(@NonNull byte[] code) {
90
        this(code, null);
1✔
91
    }
1✔
92

93
    public ClassMetadataReader(@NonNull byte[] code, @Nullable EnumSet<Attribute> attributesToRead) {
1✔
94
        this.code = code;
1✔
95
        int cpItemCount = readUnsignedShort(8);
1✔
96
        int[] cpTable = new int[cpItemCount];
1✔
97
        cpItemCodeIndexes = cpTable;
1✔
98
        this.attributesToRead = attributesToRead;
1✔
99
        cpEndIndex = findEndIndexOfConstantPoolTable(cpTable);
1✔
100
    }
1✔
101

102
    @NonNegative
103
    private int readUnsignedShort(@NonNegative int codeIndex) {
104
        byte[] b = code;
1✔
105
        int i = codeIndex;
1✔
106
        int byte0 = (b[i] & 0xFF) << 8;
1✔
107
        i++;
1✔
108
        int byte1 = b[i] & 0xFF;
1✔
109
        return byte0 | byte1;
1✔
110
    }
111

112
    private int readInt(@NonNegative int codeIndex) {
113
        byte[] b = code;
1✔
114
        int i = codeIndex;
1✔
115
        int byte0 = (b[i] & 0xFF) << 24;
1✔
116
        i++;
1✔
117
        int byte1 = (b[i] & 0xFF) << 16;
1✔
118
        i++;
1✔
119
        int byte2 = (b[i] & 0xFF) << 8;
1✔
120
        i++;
1✔
121
        int byte3 = b[i] & 0xFF;
1✔
122
        return byte0 | byte1 | byte2 | byte3;
1✔
123
    }
124

125
    @NonNegative
126
    private int findEndIndexOfConstantPoolTable(@NonNull int[] cpTable) {
127
        byte[] b = code;
1✔
128
        int codeIndex = 10;
1✔
129

130
        for (int cpItemIndex = 1, n = cpTable.length; cpItemIndex < n; cpItemIndex++) {
1✔
131
            int tagValue = b[codeIndex];
1✔
132
            codeIndex++;
1✔
133
            ConstantPoolTag tag = CONSTANT_POOL_TAGS[tagValue];
1✔
134

135
            cpTable[cpItemIndex] = codeIndex;
1✔
136

137
            int cpItemSize = tag.itemSize;
1✔
138

139
            if (tag == ConstantPoolTag.Long || tag == ConstantPoolTag.Double) {
1✔
140
                cpItemIndex++;
1✔
141
            } else if (tag == ConstantPoolTag.Utf8) {
1✔
142
                int stringLength = readUnsignedShort(codeIndex);
1✔
143
                cpItemSize += stringLength;
1✔
144
            }
145

146
            codeIndex += cpItemSize;
1✔
147
        }
148

149
        return codeIndex;
1✔
150
    }
151

152
    @NonNegative
153
    public int getVersion() {
154
        return readVersion(code);
1✔
155
    }
156

157
    @NonNegative
158
    public int getAccessFlags() {
159
        return readUnsignedShort(cpEndIndex);
1✔
160
    }
161

162
    @NonNull
163
    public String getThisClass() {
164
        int cpClassIndex = readUnsignedShort(cpEndIndex + 2);
1✔
165
        return getTypeDescription(cpClassIndex);
1✔
166
    }
167

168
    @NonNull
169
    private String getTypeDescription(@NonNegative int cpClassIndex) {
170
        int cpClassCodeIndex = cpItemCodeIndexes[cpClassIndex];
1✔
171
        int cpDescriptionIndex = readUnsignedShort(cpClassCodeIndex);
1✔
172
        return getString(cpDescriptionIndex);
1✔
173
    }
174

175
    @NonNull
176
    private String getString(@NonNegative int cpStringIndex) {
177
        int codeIndex = cpItemCodeIndexes[cpStringIndex];
1✔
178
        int stringLength = readUnsignedShort(codeIndex);
1✔
179
        return new String(code, codeIndex + 2, stringLength, UTF8);
1✔
180
    }
181

182
    @Nullable
183
    public String getSuperClass() {
184
        int cpClassIndex = readUnsignedShort(cpEndIndex + 4);
1✔
185

186
        if (cpClassIndex == 0) {
1✔
187
            return null;
1✔
188
        }
189

190
        return getTypeDescription(cpClassIndex);
1✔
191
    }
192

193
    @Nullable
194
    public String[] getInterfaces() {
195
        int codeIndex = cpEndIndex + 6;
1✔
196
        int interfaceCount = readUnsignedShort(codeIndex);
1✔
197

198
        if (interfaceCount == 0) {
1✔
199
            return null;
1✔
200
        }
201

202
        codeIndex += 2;
1✔
203

204
        String[] interfaces = new String[interfaceCount];
1✔
205

206
        for (int i = 0; i < interfaceCount; i++) {
1✔
207
            int cpInterfaceIndex = readUnsignedShort(codeIndex);
1✔
208
            codeIndex += 2;
1✔
209
            interfaces[i] = getTypeDescription(cpInterfaceIndex);
1✔
210
        }
211

212
        return interfaces;
1✔
213
    }
214

215
    private static class MemberInfo extends ObjectWithAttributes {
216
        @NonNegative
217
        public final int accessFlags;
218
        @NonNull
219
        public final String name;
220
        @NonNull
221
        public final String desc;
222
        @Nullable
223
        public String signature;
224

225
        MemberInfo(@NonNegative int accessFlags, @NonNull String name, @NonNull String desc,
226
                @NonNegative int attributeCount) {
1✔
227
            this.accessFlags = accessFlags;
1✔
228
            this.name = name;
1✔
229
            this.desc = desc;
1✔
230
        }
1✔
231

232
        public final boolean isStatic() {
233
            return (accessFlags & Access.STATIC) != 0;
1✔
234
        }
235

236
        public final boolean isAbstract() {
237
            return (accessFlags & Access.ABSTRACT) != 0;
1✔
238
        }
239

240
        public final boolean isSynthetic() {
241
            return (accessFlags & Access.SYNTHETIC) != 0;
1✔
242
        }
243
    }
244

245
    public static final class FieldInfo extends MemberInfo {
246
        FieldInfo(int accessFlags, @NonNull String name, @NonNull String desc, @NonNegative int attributeCount) {
247
            super(accessFlags, name, desc, attributeCount);
1✔
248
        }
1✔
249
    }
250

251
    @NonNull
252
    public List<FieldInfo> getFields() {
253
        int codeIndex = cpEndIndex + 6;
1✔
254
        int interfaceCount = readUnsignedShort(codeIndex);
1✔
255
        codeIndex += 2 + 2 * interfaceCount;
1✔
256

257
        int fieldCount = readUnsignedShort(codeIndex);
1✔
258
        codeIndex += 2;
1✔
259

260
        List<FieldInfo> fields;
261

262
        if (fieldCount == 0) {
1!
NEW
263
            fields = List.of();
×
264
        } else {
265
            fields = new ArrayList<>(fieldCount);
1✔
266

267
            for (int i = 0; i < fieldCount; i++) {
1✔
268
                int accessFlags = readUnsignedShort(codeIndex);
1✔
269
                codeIndex += 2;
1✔
270

271
                int cpNameIndex = readUnsignedShort(codeIndex);
1✔
272
                codeIndex += 2;
1✔
273
                String fieldName = getString(cpNameIndex);
1✔
274

275
                int cpDescIndex = readUnsignedShort(codeIndex);
1✔
276
                codeIndex += 2;
1✔
277
                String fieldDesc = getString(cpDescIndex);
1✔
278

279
                int attributeCount = readUnsignedShort(codeIndex);
1✔
280
                codeIndex += 2;
1✔
281

282
                FieldInfo fieldInfo = new FieldInfo(accessFlags, fieldName, fieldDesc, attributeCount);
1✔
283
                codeIndex = readAttributes(attributeCount, fieldInfo, codeIndex);
1✔
284
                fields.add(fieldInfo);
1✔
285
            }
286
        }
287

288
        fieldsEndIndex = codeIndex;
1✔
289
        return fields;
1✔
290
    }
291

292
    @NonNegative
293
    private int readAttributes(@NonNegative int attributeCount, @Nullable ObjectWithAttributes attributeOwner,
294
            @NonNegative int codeIndex) {
295
        EnumSet<Attribute> attributes = attributesToRead;
1✔
296
        boolean readAnnotations = false;
1✔
297

298
        if (attributes == null) {
1✔
299
            // noinspection AssignmentToMethodParameter
300
            attributeOwner = null;
1✔
301
        } else {
302
            readAnnotations = attributes.contains(Attribute.Annotations);
1✔
303
        }
304

305
        MethodInfo method = attributeOwner instanceof MethodInfo ? (MethodInfo) attributeOwner : null;
1✔
306

307
        for (int i = 0; i < attributeCount; i++) {
1✔
308
            int cpNameIndex = readUnsignedShort(codeIndex);
1✔
309
            codeIndex += 2;
1✔
310
            String attributeName = getString(cpNameIndex);
1✔
311

312
            int attributeLength = readInt(codeIndex);
1✔
313
            codeIndex += 4;
1✔
314

315
            if (attributeOwner != null) {
1✔
316
                if (method != null) {
1✔
317
                    method.readAttributes(attributeName, codeIndex);
1✔
318
                }
319

320
                if (readAnnotations && "RuntimeVisibleAnnotations".equals(attributeName)) {
1✔
321
                    attributeOwner.annotations = readAnnotations(codeIndex);
1✔
322
                }
323
            }
324

325
            codeIndex += attributeLength;
1✔
326
        }
327

328
        return codeIndex;
1✔
329
    }
330

331
    public static final class AnnotationInfo {
332
        @NonNull
333
        public final String name;
334

335
        AnnotationInfo(@NonNull String name) {
1✔
336
            this.name = name;
1✔
337
        }
1✔
338
    }
339

340
    @NonNull
341
    private List<AnnotationInfo> readAnnotations(@NonNegative int codeIndex) {
342
        int numAnnotations = readUnsignedShort(codeIndex);
1✔
343
        codeIndex += 2;
1✔
344

345
        List<AnnotationInfo> annotationInfos = new ArrayList<>(numAnnotations);
1✔
346

347
        for (int i = 0; i < numAnnotations; i++) {
1✔
348
            codeIndex = readAnnotation(annotationInfos, codeIndex);
1✔
349
        }
350

351
        return annotationInfos;
1✔
352
    }
353

354
    @NonNegative
355
    private int readAnnotation(@NonNull List<AnnotationInfo> currentAnnotations, @NonNegative int codeIndex) {
356
        int cpTypeIndex = readUnsignedShort(codeIndex);
1✔
357
        codeIndex += 2;
1✔
358

359
        String annotationTypeDesc = getString(cpTypeIndex);
1✔
360

361
        readUnsignedShort(codeIndex);
1✔
362
        codeIndex += 2;
1✔
363

364
        // for (int i = 0; i < numElementValuePairs; i++) {
365
        // int cpElementNameIndex = readUnsignedShort(codeIndex);
366
        // codeIndex += 2;
367
        //
368
        // int tag = code[codeIndex++];
369
        // // TODO: continue implementing
370
        // }
371

372
        AnnotationInfo annotation = new AnnotationInfo(annotationTypeDesc);
1✔
373
        currentAnnotations.add(annotation);
1✔
374

375
        return codeIndex;
1✔
376
    }
377

378
    @NonNegative
379
    private int getFieldsEndIndex() {
380
        int codeIndex = fieldsEndIndex;
1✔
381

382
        if (codeIndex == 0) {
1!
383
            codeIndex = cpEndIndex + 6;
1✔
384
            int interfaceCount = readUnsignedShort(codeIndex);
1✔
385
            codeIndex += 2 + 2 * interfaceCount;
1✔
386

387
            int fieldCount = readUnsignedShort(codeIndex);
1✔
388
            codeIndex += 2;
1✔
389

390
            for (int i = 0; i < fieldCount; i++) {
1✔
391
                codeIndex += 6;
1✔
392

393
                int attributeCount = readUnsignedShort(codeIndex);
1✔
394
                codeIndex += 2;
1✔
395

396
                codeIndex = readAttributes(attributeCount, null, codeIndex);
1✔
397
            }
398

399
            fieldsEndIndex = codeIndex;
1✔
400
        }
401

402
        return codeIndex;
1✔
403
    }
404

405
    public final class MethodInfo extends MemberInfo {
1✔
406
        @Nullable
407
        public String[] parameters;
408

409
        MethodInfo(int accessFlags, @NonNull String name, @NonNull String desc, @NonNegative int attributeCount) {
1✔
410
            super(accessFlags, name, desc, attributeCount);
1✔
411
        }
1✔
412

413
        public boolean isMethod() {
414
            return name.charAt(0) != '<';
1✔
415
        }
416

417
        public boolean isConstructor() {
418
            return "<init>".equals(name);
1✔
419
        }
420

421
        void readAttributes(@NonNull String attributeName, @NonNegative int codeIndex) {
422
            assert attributesToRead != null;
1!
423

424
            if ("Code".equals(attributeName)) {
1✔
425
                if (attributesToRead.contains(Attribute.Parameters)) {
1✔
426
                    readParameters(codeIndex);
1✔
427
                }
428
            } else if ("Signature".equals(attributeName) && attributesToRead.contains(Attribute.Signature)) {
1✔
429
                readSignature(codeIndex);
1✔
430
            }
431
        }
1✔
432

433
        private void readParameters(@NonNegative int codeIndex) {
434
            codeIndex += 4;
1✔
435

436
            int codeLength = readInt(codeIndex);
1✔
437
            codeIndex += 4 + codeLength;
1✔
438

439
            int exceptionTableLength = readUnsignedShort(codeIndex);
1✔
440
            codeIndex += 2 + 8 * exceptionTableLength;
1✔
441

442
            int attributeCount = readUnsignedShort(codeIndex);
1✔
443
            codeIndex += 2;
1✔
444

445
            readParameters(attributeCount, codeIndex);
1✔
446
        }
1✔
447

448
        private void readParameters(@NonNegative int attributeCount, @NonNegative int codeIndex) {
449
            for (int i = 0; i < attributeCount; i++) {
1✔
450
                int cpNameIndex = readUnsignedShort(codeIndex);
1✔
451
                codeIndex += 2;
1✔
452
                String attributeName = getString(cpNameIndex);
1✔
453

454
                int attributeLength = readInt(codeIndex);
1✔
455
                codeIndex += 4;
1✔
456

457
                if ("LocalVariableTable".equals(attributeName)) {
1✔
458
                    parameters = readParametersFromLocalVariableTable(codeIndex);
1✔
459
                    break;
1✔
460
                }
461

462
                codeIndex += attributeLength;
1✔
463
            }
464
        }
1✔
465

466
        @Nullable
467
        private String[] readParametersFromLocalVariableTable(@NonNegative int codeIndex) {
468
            int localVariableTableLength = readUnsignedShort(codeIndex);
1✔
469
            codeIndex += 2;
1✔
470

471
            int arraySize = getSumOfArgumentSizes(desc);
1✔
472

473
            if (arraySize == 0) {
1✔
474
                return null;
1✔
475
            }
476

477
            if (!isStatic()) {
1✔
478
                arraySize++;
1✔
479
            }
480

481
            String[] parameterNames = new String[arraySize];
1✔
482

483
            for (int i = 0; i < localVariableTableLength; i++) {
1✔
484
                codeIndex += 4;
1✔
485

486
                int cpLocalVarNameIndex = readUnsignedShort(codeIndex);
1✔
487
                codeIndex += 2;
1✔
488
                String localVarName = getString(cpLocalVarNameIndex);
1✔
489

490
                if ("this".equals(localVarName)) {
1✔
491
                    codeIndex += 4;
1✔
492
                    continue;
1✔
493
                }
494

495
                codeIndex += 2;
1✔
496

497
                int localVarIndex = readUnsignedShort(codeIndex);
1✔
498
                codeIndex += 2;
1✔
499

500
                if (localVarIndex < arraySize) {
1✔
501
                    parameterNames[localVarIndex] = localVarName;
1✔
502
                }
503
            }
504

505
            return compactArray(parameterNames);
1✔
506
        }
507

508
        @NonNegative
509
        private int getSumOfArgumentSizes(@NonNull String memberDesc) {
510
            int sum = 0;
1✔
511
            int i = 1;
1✔
512

513
            while (true) {
514
                char c = memberDesc.charAt(i);
1✔
515
                i++;
1✔
516

517
                switch (c) {
1✔
518
                    case ')':
519
                        return sum;
1✔
520
                    case 'L':
521
                        while (memberDesc.charAt(i) != ';') {
1✔
522
                            i++;
1✔
523
                        }
524
                        i++;
1✔
525
                        sum++;
1✔
526
                        break;
1✔
527
                    case '[':
528
                        while ((c = memberDesc.charAt(i)) == '[') {
1!
529
                            i++;
×
530
                        }
531
                        if (isDoubleSizeType(c)) { // if the array element type is double size...
1!
532
                            i++;
×
533
                            sum++; // ...then count it here, otherwise let the outer loop count it
×
534
                        }
535
                        break;
536
                    default:
537
                        if (isDoubleSizeType(c)) {
1✔
538
                            sum += 2;
1✔
539
                        } else {
540
                            sum++;
1✔
541
                        }
542
                        break;
543
                }
544
            }
1✔
545
        }
546

547
        private boolean isDoubleSizeType(char typeCode) {
548
            return typeCode == 'D' || typeCode == 'J';
1✔
549
        }
550

551
        @Nullable
552
        private String[] compactArray(@NonNull String[] arrayPossiblyWithNulls) {
553
            int n = arrayPossiblyWithNulls.length;
1✔
554
            int j = n - 1;
1✔
555
            int i = 0;
1✔
556

557
            while (i < j) {
1✔
558
                if (arrayPossiblyWithNulls[i] == null) {
1✔
559
                    System.arraycopy(arrayPossiblyWithNulls, i + 1, arrayPossiblyWithNulls, i, j - i);
1✔
560
                    arrayPossiblyWithNulls[j] = null;
1✔
561
                    j--;
1✔
562
                } else {
563
                    i++;
1✔
564
                }
565
            }
566

567
            return n == 1 && arrayPossiblyWithNulls[0] == null ? null : arrayPossiblyWithNulls;
1!
568
        }
569

570
        private void readSignature(@NonNegative int codeIndex) {
571
            int cpSignatureIndex = readUnsignedShort(codeIndex);
1✔
572
            signature = getString(cpSignatureIndex);
1✔
573
        }
1✔
574
    }
575

576
    @NonNull
577
    public List<MethodInfo> getMethods() {
578
        int codeIndex = getFieldsEndIndex();
1✔
579
        int methodCount = readUnsignedShort(codeIndex);
1✔
580
        codeIndex += 2;
1✔
581

582
        List<MethodInfo> methods = new ArrayList<>(methodCount);
1✔
583

584
        for (int i = 0; i < methodCount; i++) {
1✔
585
            int accessFlags = readUnsignedShort(codeIndex);
1✔
586
            codeIndex += 2;
1✔
587

588
            int cpNameIndex = readUnsignedShort(codeIndex);
1✔
589
            codeIndex += 2;
1✔
590
            String methodName = getString(cpNameIndex);
1✔
591

592
            int cpDescIndex = readUnsignedShort(codeIndex);
1✔
593
            codeIndex += 2;
1✔
594
            String methodDesc = getString(cpDescIndex);
1✔
595

596
            int attributeCount = readUnsignedShort(codeIndex);
1✔
597
            codeIndex += 2;
1✔
598

599
            MethodInfo methodInfo = new MethodInfo(accessFlags, methodName, methodDesc, attributeCount);
1✔
600
            codeIndex = readAttributes(attributeCount, methodInfo, codeIndex);
1✔
601
            methods.add(methodInfo);
1✔
602
        }
603

604
        methodsEndIndex = codeIndex;
1✔
605
        return methods;
1✔
606
    }
607

608
    @NonNegative
609
    private int getMethodsEndIndex() {
610
        int codeIndex = methodsEndIndex;
1✔
611

612
        if (codeIndex == 0) {
1!
613
            codeIndex = getFieldsEndIndex();
1✔
614

615
            int methodCount = readUnsignedShort(codeIndex);
1✔
616
            codeIndex += 2;
1✔
617

618
            for (int i = 0; i < methodCount; i++) {
1✔
619
                codeIndex += 6;
1✔
620

621
                int attributeCount = readUnsignedShort(codeIndex);
1✔
622
                codeIndex += 2;
1✔
623

624
                codeIndex = readAttributes(attributeCount, null, codeIndex);
1✔
625
            }
626

627
            methodsEndIndex = codeIndex;
1✔
628
        }
629

630
        return codeIndex;
1✔
631
    }
632

633
    @NonNull
634
    public List<AnnotationInfo> getAnnotations() {
635
        if (annotations == null) {
1!
636
            int codeIndex = getMethodsEndIndex();
1✔
637
            int attributeCount = readUnsignedShort(codeIndex);
1✔
638
            codeIndex += 2;
1✔
639

640
            readAttributes(attributeCount, this, codeIndex);
1✔
641

642
            if (annotations == null) {
1!
NEW
643
                annotations = List.of();
×
644
            }
645
        }
646

647
        return annotations;
1✔
648
    }
649
}
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