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

raphw / byte-buddy / #776

15 Jun 2025 10:22PM UTC coverage: 85.136% (-0.04%) from 85.177%
#776

push

raphw
Add additional test and assure lazy resolution of some modifier properties.

4 of 4 new or added lines in 1 file covered. (100.0%)

597 existing lines in 5 files now uncovered.

29538 of 34695 relevant lines covered (85.14%)

0.85 hits per line

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

45.87
/byte-buddy-dep/src/main/java/net/bytebuddy/utility/AsmClassWriter.java
1
/*
2
 * Copyright 2014 - Present Rafael Winterhalter
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package net.bytebuddy.utility;
17

18
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19
import net.bytebuddy.ClassFileVersion;
20
import net.bytebuddy.build.AccessControllerPlugin;
21
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
22
import net.bytebuddy.description.type.TypeDescription;
23
import net.bytebuddy.pool.TypePool;
24
import net.bytebuddy.utility.dispatcher.JavaDispatcher;
25
import net.bytebuddy.utility.nullability.AlwaysNull;
26
import net.bytebuddy.utility.nullability.MaybeNull;
27
import net.bytebuddy.utility.privilege.GetSystemPropertyAction;
28
import org.objectweb.asm.ClassReader;
29
import org.objectweb.asm.ClassVisitor;
30
import org.objectweb.asm.ClassWriter;
31

32
import java.lang.reflect.Method;
33
import java.security.PrivilegedAction;
34
import java.util.List;
35

36
/**
37
 * A facade for creating a {@link ClassVisitor} that writes a class file.
38
 */
39
public interface AsmClassWriter {
40

41
    /**
42
     * Returns the {@link ClassVisitor} to use for writing the class file.
43
     *
44
     * @return An appropriate class visitor.
45
     */
46
    ClassVisitor getVisitor();
47

48
    /**
49
     * Returns the binary representation of the created class file.
50
     *
51
     * @return The binary representation of the created class file.
52
     */
53
    byte[] getBinaryRepresentation();
54

55
    /**
56
     * A factory for creating an {@link AsmClassWriter}.
57
     */
58
    interface Factory {
59

60
        /**
61
         * Creates a new class writer for the given flags.
62
         *
63
         * @param flags The flags to consider while writing a class file.
64
         * @return An appropriate class writer.
65
         */
66
        AsmClassWriter make(int flags);
67

68
        /**
69
         * Creates a new class writer for the given flags, possibly based on a previous class file representation.
70
         *
71
         * @param flags       The flags to consider while writing a class file.
72
         * @param classReader A class reader to consider for writing a class file.
73
         * @return An appropriate class writer.
74
         */
75
        AsmClassWriter make(int flags, AsmClassReader classReader);
76

77
        /**
78
         * Creates a new class writer for the given flags.
79
         *
80
         * @param flags    The flags to consider while writing a class file.
81
         * @param typePool A type pool to use for resolving type information for frame generation.
82
         * @return An appropriate class writer.
83
         */
84
        AsmClassWriter make(int flags, TypePool typePool);
85

86
        /**
87
         * Creates a new class writer for the given flags, possibly based on a previous class file representation.
88
         *
89
         * @param flags       The flags to consider while writing a class file.
90
         * @param classReader A class reader to consider for writing a class file.
91
         * @param typePool    A type pool to use for resolving type information for frame generation.
92
         * @return An appropriate class writer.
93
         */
94
        AsmClassWriter make(int flags, AsmClassReader classReader, TypePool typePool);
95

96
        /**
97
         * Default implementations for factories of {@link AsmClassWriter}s.
98
         */
99
        enum Default implements Factory {
1✔
100

101
            /**
102
             * Uses a processor as it is configured by {@link OpenedClassReader#PROCESSOR_PROPERTY},
103
             * or {@link Default#ASM_FIRST} if no implicit processor is defined.
104
             */
105
            IMPLICIT {
1✔
106
                /**
107
                 * {@inheritDoc}
108
                 */
109
                public AsmClassWriter make(int flags, AsmClassReader classReader, TypePool typePool) {
110
                    return (FACTORY == IMPLICIT ? ASM_FIRST : FACTORY).make(flags, classReader, typePool);
1✔
111
                }
112
            },
113

114
            /**
115
             * A factory for a class reader that uses ASM's internal implementation whenever possible.
116
             */
117
            ASM_FIRST {
1✔
118
                /**
119
                 * {@inheritDoc}
120
                 */
121
                public AsmClassWriter make(int flags, AsmClassReader classReader, TypePool typePool) {
122
                    return ClassFileVersion.ofThisVm().isGreaterThan(ClassFileVersion.latest())
1✔
123
                            ? CLASS_FILE_API_ONLY.make(flags, classReader, typePool)
1✔
124
                            : ASM_ONLY.make(flags, classReader, typePool);
1✔
125
                }
126
            },
127

128
            /**
129
             * A factory for a class writer that uses the class file API whenever possible.
130
             */
131
            CLASS_FILE_API_FIRST {
1✔
132
                /**
133
                 * {@inheritDoc}
134
                 */
135
                public AsmClassWriter make(int flags, AsmClassReader classReader, TypePool typePool) {
136
                    return ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V24)
×
137
                            ? CLASS_FILE_API_ONLY.make(flags, classReader, typePool)
×
UNCOV
138
                            : ASM_ONLY.make(flags, classReader, typePool);
×
139
                }
140
            },
141

142
            /**
143
             * A factory that will always use ASM's internal implementation.
144
             */
145
            ASM_ONLY {
1✔
146
                /**
147
                 * {@inheritDoc}
148
                 */
149
                public AsmClassWriter make(int flags, AsmClassReader classReader, TypePool typePool) {
150
                    ClassReader unwrapped = classReader.unwrap(ClassReader.class);
1✔
151
                    return new ForAsm(unwrapped == null
1✔
152
                            ? new FrameComputingClassWriter(flags, typePool)
153
                            : new FrameComputingClassWriter(unwrapped, flags, typePool));
154
                }
155
            },
156

157
            /**
158
             * A factory that will always use the Class File API.
159
             */
160
            CLASS_FILE_API_ONLY {
1✔
161
                /**
162
                 * {@inheritDoc}
163
                 */
164
                @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "False positive in FindBugs.")
165
                public AsmClassWriter make(int flags, AsmClassReader classReader, TypePool typePool) {
166
                    Object jdkClassReader = JDK_CLASS_READER == null ? null : classReader.unwrap(JDK_CLASS_READER);
×
167
                    if (jdkClassReader == null) {
×
UNCOV
168
                        return new ForClassFileApi(ForClassFileApi.DISPATCHER.make(flags,
×
169
                                SuperClassResolvingJdkClassWriter.GET_SUPER_CLASS,
170
                                new SuperClassResolvingJdkClassWriter(typePool)));
171
                    } else {
UNCOV
172
                        return new ForClassFileApi(ForClassFileApi.DISPATCHER.make(jdkClassReader,
×
173
                                flags,
174
                                SuperClassResolvingJdkClassWriter.GET_SUPER_CLASS,
175
                                new SuperClassResolvingJdkClassWriter(typePool)));
176
                    }
177
                }
178
            };
179

180
            /**
181
             * The {@code codes.rafael.asmjdkbridge.JdkClassReader} type or {@code null} if not available.
182
             */
183
            @MaybeNull
184
            private static final Class<?> JDK_CLASS_READER;
185

186
            /**
187
             * The implicit factory to use for writing class files.
188
             */
189
            private static final Factory FACTORY;
190

191
            /*
192
             * Resolves the implicit writer factory, if any and locates a possible {@code JdkClassReader} type.
193
             */
194
            static {
195
                String processor;
196
                try {
197
                    processor = doPrivileged(new GetSystemPropertyAction(OpenedClassReader.PROCESSOR_PROPERTY));
1✔
198
                } catch (Throwable ignored) {
×
UNCOV
199
                    processor = null;
×
200
                }
1✔
201
                FACTORY = processor == null ? Default.ASM_FIRST : Default.valueOf(processor);
1✔
202
                Class<?> type;
203
                try {
204
                    type = ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V24)
1✔
205
                        ? Class.forName("codes.rafael.asmjdkbridge.JdkClassReader")
1✔
206
                        : null;
207
                } catch (ClassNotFoundException ignored) {
×
UNCOV
208
                    type = null;
×
209
                }
1✔
210
                JDK_CLASS_READER = type;
1✔
211
            }
1✔
212

213
            /**
214
             * A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
215
             *
216
             * @param action The action to execute from a privileged context.
217
             * @param <T>    The type of the action's resolved value.
218
             * @return The action's resolved value.
219
             */
220
            @MaybeNull
221
            @AccessControllerPlugin.Enhance
222
            private static <T> T doPrivileged(PrivilegedAction<T> action) {
UNCOV
223
                return action.run();
×
224
            }
225

226
            /**
227
             * {@inheritDoc}
228
             */
229
            public AsmClassWriter make(int flags) {
230
                return make(flags, TypePool.Empty.INSTANCE);
1✔
231
            }
232

233
            /**
234
             * {@inheritDoc}
235
             */
236
            public AsmClassWriter make(int flags, AsmClassReader classReader) {
237
                return make(flags, classReader, TypePool.Empty.INSTANCE);
1✔
238
            }
239

240
            /**
241
             * {@inheritDoc}
242
             */
243
            public AsmClassWriter make(int flags, TypePool typePool) {
244
                return make(flags, EmptyAsmClassReader.INSTANCE, typePool);
1✔
245
            }
246

247
            /**
248
             * An empty class reader for ASM that never unwraps an underlying implementation.
249
             */
250
            protected enum EmptyAsmClassReader implements AsmClassReader {
1✔
251

252
                /**
253
                 * The singleton instance.
254
                 */
255
                INSTANCE;
1✔
256

257
                /**
258
                 * {@inheritDoc}
259
                 */
260
                @AlwaysNull
261
                public AsmClassWriter toWriter(int flags, TypePool typePool) {
UNCOV
262
                    return null;
×
263
                }
264

265
                /**
266
                 * {@inheritDoc}
267
                 */
268
                @AlwaysNull
269
                public <T> T unwrap(Class<T> type) {
270
                    return null;
1✔
271
                }
272

273
                /**
274
                 * {@inheritDoc}
275
                 */
276
                public int getModifiers() {
UNCOV
277
                    throw new UnsupportedOperationException();
×
278
                }
279

280
                /**
281
                 * {@inheritDoc}
282
                 */
283
                public String getInternalName() {
UNCOV
284
                    throw new UnsupportedOperationException();
×
285
                }
286

287
                /**
288
                 * {@inheritDoc}
289
                 */
290
                public String getSuperClassInternalName() {
UNCOV
291
                    throw new UnsupportedOperationException();
×
292
                }
293

294
                /**
295
                 * {@inheritDoc}
296
                 */
297
                public List<String> getInterfaceInternalNames() {
UNCOV
298
                    throw new UnsupportedOperationException();
×
299
                }
300

301
                /**
302
                 * {@inheritDoc}
303
                 */
304
                public void accept(ClassVisitor classVisitor, int flags) {
UNCOV
305
                    throw new UnsupportedOperationException();
×
306
                }
307
            }
308

309
            /**
310
             * A class reader that does not retain a compatible {@link AsmClassWriter} implementation.
311
             */
312
            public static class NonRetainingAsmClassReader implements AsmClassReader {
313

314
                /**
315
                 * The delegate implementation.
316
                 */
317
                private final AsmClassReader delegate;
318

319
                /**
320
                 * Creates a new non-retaining ASM class writer.
321
                 *
322
                 * @param delegate The delegate implementation.
323
                 */
UNCOV
324
                public NonRetainingAsmClassReader(AsmClassReader delegate) {
×
UNCOV
325
                    this.delegate = delegate;
×
UNCOV
326
                }
×
327

328
                /**
329
                 * {@inheritDoc}
330
                 */
331
                @MaybeNull
332
                public <T> T unwrap(Class<T> type) {
UNCOV
333
                    return delegate.unwrap(type);
×
334
                }
335

336
                /**
337
                 * {@inheritDoc}
338
                 */
339
                @AlwaysNull
340
                public AsmClassWriter toWriter(int flags, TypePool typePool) {
341
                    return null;
×
342
                }
343

344
                /**
345
                 * {@inheritDoc}
346
                 */
347
                public int getModifiers() {
UNCOV
348
                    return delegate.getModifiers();
×
349
                }
350

351
                /**
352
                 * {@inheritDoc}
353
                 */
354
                public String getInternalName() {
UNCOV
355
                    return delegate.getInternalName();
×
356
                }
357

358
                /**
359
                 * {@inheritDoc}
360
                 */
361
                @MaybeNull
362
                public String getSuperClassInternalName() {
363
                    return delegate.getSuperClassInternalName();
×
364
                }
365

366
                /**
367
                 * {@inheritDoc}
368
                 */
369
                public List<String> getInterfaceInternalNames() {
370
                    return delegate.getInterfaceInternalNames();
×
371
                }
372

373
                /**
374
                 * {@inheritDoc}
375
                 */
376
                public void accept(ClassVisitor classVisitor, int flags) {
UNCOV
377
                    delegate.accept(classVisitor, flags);
×
UNCOV
378
                }
×
379
            }
380
        }
381

382
        /**
383
         * A class writer factory that suppresses any class reader implementation that might be provided
384
         * upon constructing a class writer.
385
         */
386
        @HashCodeAndEqualsPlugin.Enhance
387
        class Suppressing implements Factory {
388

389
            /**
390
             * The factory to delegate to.
391
             */
392
            private final Factory delegate;
393

394
            /**
395
             * Creates a suppressing class writer factory.
396
             *
397
             * @param delegate The factory to delegate to.
398
             */
UNCOV
399
            public Suppressing(Factory delegate) {
×
UNCOV
400
                this.delegate = delegate;
×
UNCOV
401
            }
×
402

403
            /**
404
             * {@inheritDoc}
405
             */
406
            public AsmClassWriter make(int flags) {
UNCOV
407
                return delegate.make(flags);
×
408
            }
409

410
            /**
411
             * {@inheritDoc}
412
             */
413
            public AsmClassWriter make(int flags, AsmClassReader classReader) {
UNCOV
414
                return delegate.make(flags);
×
415
            }
416

417
            /**
418
             * {@inheritDoc}
419
             */
420
            public AsmClassWriter make(int flags, TypePool typePool) {
UNCOV
421
                return delegate.make(flags, typePool);
×
422
            }
423

424
            /**
425
             * {@inheritDoc}
426
             */
427
            public AsmClassWriter make(int flags, AsmClassReader classReader, TypePool typePool) {
UNCOV
428
                return delegate.make(flags, typePool);
×
429
            }
430
        }
431
    }
432

433
    /**
434
     * Am implementation that uses ASM's internal {@link ClassWriter}.
435
     */
436
    class ForAsm implements AsmClassWriter {
437

438
        /**
439
         * The represented class writer.
440
         */
441
        private final ClassWriter classWriter;
442

443
        /**
444
         * Creates a new class writer based upon ASM's own implementation.
445
         *
446
         * @param classWriter The represented class writer.
447
         */
448
        public ForAsm(ClassWriter classWriter) {
1✔
449
            this.classWriter = classWriter;
1✔
450
        }
1✔
451

452
        /**
453
         * {@inheritDoc}
454
         */
455
        public ClassVisitor getVisitor() {
456
            return classWriter;
1✔
457
        }
458

459
        /**
460
         * {@inheritDoc}
461
         */
462
        public byte[] getBinaryRepresentation() {
463
            return classWriter.toByteArray();
1✔
464
        }
465
    }
466

467
    /**
468
     * A Class File API-based implementation for a class writer.
469
     */
470
    class ForClassFileApi implements AsmClassWriter {
471

472
        /**
473
         * The dispatcher for interacting with a {@code codes.rafael.asmjdkbridge.JdkClassWriter}.
474
         */
UNCOV
475
        private static final JdkClassWriter DISPATCHER = doPrivileged(JavaDispatcher.of(
×
476
                JdkClassWriter.class,
UNCOV
477
                ForClassFileApi.class.getClassLoader()));
×
478

479
        /**
480
         * The represented class writer.
481
         */
482
        private final ClassVisitor classWriter;
483

484
        /**
485
         * Creates a new class file API-based class writer.
486
         *
487
         * @param classWriter The represented class writer.
488
         */
UNCOV
489
        public ForClassFileApi(ClassVisitor classWriter) {
×
UNCOV
490
            if (!DISPATCHER.isInstance(classWriter)) {
×
UNCOV
491
                throw new IllegalArgumentException("Not a JDK class writer: " + classWriter);
×
492
            }
UNCOV
493
            this.classWriter = classWriter;
×
UNCOV
494
        }
×
495

496
        /**
497
         * A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
498
         *
499
         * @param action The action to execute from a privileged context.
500
         * @param <T>    The type of the action's resolved value.
501
         * @return The action's resolved value.
502
         */
503
        @AccessControllerPlugin.Enhance
504
        private static <T> T doPrivileged(PrivilegedAction<T> action) {
UNCOV
505
            return action.run();
×
506
        }
507

508
        /**
509
         * {@inheritDoc}
510
         */
511
        public ClassVisitor getVisitor() {
UNCOV
512
            return classWriter;
×
513
        }
514

515
        /**
516
         * {@inheritDoc}
517
         */
518
        public byte[] getBinaryRepresentation() {
UNCOV
519
            return DISPATCHER.toByteArray(classWriter);
×
520
        }
521

522
        /**
523
         * An API to interact with {@code codes.rafael.asmjdkbridge.JdkClassWriter}.
524
         */
525
        @JavaDispatcher.Proxied("codes.rafael.asmjdkbridge.JdkClassWriter")
526
        protected interface JdkClassWriter {
527

528
            /**
529
             * Checks if the supplied instance is a {@code codes.rafael.asmjdkbridge.JdkClassWriter}.
530
             *
531
             * @param value The value to evaluate.
532
             * @return {@code true} if the supplied instance is a  {@code codes.rafael.asmjdkbridge.JdkClassWriter}.
533
             */
534
            @JavaDispatcher.Instance
535
            boolean isInstance(ClassVisitor value);
536

537
            /**
538
             * Create a new {@code codes.rafael.asmjdkbridge.JdkClassWriter}.
539
             *
540
             * @param flags         The flags to consider.
541
             * @param getSuperClass A resolver for the super class.
542
             * @param target        The target to invoke the super class resolver upon.
543
             * @return A new {@code codes.rafael.asmjdkbridge.JdkClassWriter}.
544
             */
545
            @JavaDispatcher.IsConstructor
546
            ClassVisitor make(int flags, Method getSuperClass, Object target);
547

548
            /**
549
             * Create a new {@code codes.rafael.asmjdkbridge.JdkClassWriter}.
550
             *
551
             * @param classReader   The class reader of which to reuse the constant pool.
552
             * @param flags         The flags to consider.
553
             * @param getSuperClass A resolver for the super class.
554
             * @param target        The target to invoke the super class resolver upon.
555
             * @return A new {@code codes.rafael.asmjdkbridge.JdkClassWriter}.
556
             */
557
            @JavaDispatcher.IsConstructor
558
            ClassVisitor make(@JavaDispatcher.Proxied("codes.rafael.asmjdkbridge.JdkClassReader") Object classReader,
559
                              int flags,
560
                              Method getSuperClass,
561
                              Object target);
562

563
            /**
564
             * Reads the created class file byte array from a given {@code codes.rafael.asmjdkbridge.JdkClassWriter}.
565
             *
566
             * @param value The {@code codes.rafael.asmjdkbridge.JdkClassWriter} to read from.
567
             * @return The generated class file.
568
             */
569
            byte[] toByteArray(ClassVisitor value);
570
        }
571
    }
572

573
    /**
574
     * A class writer that piggy-backs on Byte Buddy's {@link TypePool} to avoid class loading or look-up errors when redefining a class.
575
     * This is not available when creating a new class where automatic frame computation is however not normally a requirement.
576
     */
577
    class FrameComputingClassWriter extends ClassWriter {
578

579
        /**
580
         * The type pool to use for computing stack map frames, if required.
581
         */
582
        private final TypePool typePool;
583

584
        /**
585
         * Creates a new frame computing class writer.
586
         *
587
         * @param flags    The flags to be handed to the writer.
588
         * @param typePool The type pool to use for computing stack map frames, if required.
589
         */
590
        public FrameComputingClassWriter(int flags, TypePool typePool) {
591
            super(flags);
1✔
592
            this.typePool = typePool;
1✔
593
        }
1✔
594

595
        /**
596
         * Creates a new frame computing class writer.
597
         *
598
         * @param classReader The class reader from which the original class is read.
599
         * @param flags       The flags to be handed to the writer.
600
         * @param typePool    The type pool to use for computing stack map frames, if required.
601
         */
602
        public FrameComputingClassWriter(ClassReader classReader, int flags, TypePool typePool) {
603
            super(classReader, flags);
1✔
604
            this.typePool = typePool;
1✔
605
        }
1✔
606

607
        /**
608
         * {@inheritDoc}
609
         */
610
        protected String getCommonSuperClass(String leftTypeName, String rightTypeName) {
611
            TypeDescription leftType = typePool.describe(leftTypeName.replace('/', '.')).resolve();
1✔
612
            TypeDescription rightType = typePool.describe(rightTypeName.replace('/', '.')).resolve();
1✔
613
            if (leftType.isAssignableFrom(rightType)) {
1✔
614
                return leftType.getInternalName();
1✔
615
            } else if (leftType.isAssignableTo(rightType)) {
1✔
616
                return rightType.getInternalName();
1✔
617
            } else if (leftType.isInterface() || rightType.isInterface()) {
1✔
618
                return TypeDescription.ForLoadedType.of(Object.class).getInternalName();
1✔
619
            } else {
620
                do {
621
                    TypeDescription.Generic superClass = leftType.getSuperClass();
1✔
622
                    if (superClass == null) {
1✔
623
                        return TypeDescription.ForLoadedType.of(Object.class).getInternalName();
×
624
                    }
625
                    leftType = superClass.asErasure();
1✔
626
                } while (!leftType.isAssignableFrom(rightType));
1✔
627
                return leftType.getInternalName();
1✔
628
            }
629
        }
630
    }
631

632
    /**
633
     * A pseudo-JDK class writer that resolves super classes using a {@link TypePool}, to pass in the constructor.
634
     */
635
    class SuperClassResolvingJdkClassWriter {
636

637
        /**
638
         * The {@link SuperClassResolvingJdkClassWriter#getSuperClass(String)} method.
639
         */
640
        protected static final Method GET_SUPER_CLASS;
641

642
        /*
643
         * Resolve the method instance to use for reflection.
644
         */
645
        static {
646
            Method getSuperClass;
647
            try {
UNCOV
648
                getSuperClass = SuperClassResolvingJdkClassWriter.class.getMethod("getSuperClass", String.class);
×
UNCOV
649
            } catch (NoSuchMethodException e) {
×
UNCOV
650
                throw new IllegalStateException("Failed to resolve own method", e);
×
UNCOV
651
            }
×
UNCOV
652
            GET_SUPER_CLASS = getSuperClass;
×
UNCOV
653
        }
×
654

655
        /**
656
         * The {@link TypePool} to use.
657
         */
658
        private final TypePool typePool;
659

660
        /**
661
         * Creates a super class resolving JDK class writer.
662
         *
663
         * @param typePool The {@link TypePool} to use.
664
         */
UNCOV
665
        public SuperClassResolvingJdkClassWriter(TypePool typePool) {
×
UNCOV
666
            this.typePool = typePool;
×
UNCOV
667
        }
×
668

669
        /**
670
         * Resolves the super class for a given internal class name, or {@code null} if a given class
671
         * represents an interface. The provided class name will never be {@link Object}.
672
         *
673
         * @param internalName The internal name of the class or interface of which to return a super type.
674
         * @return The internal name of the super class or {@code null} if the provided type name represents
675
         * an interface.
676
         */
677
        @MaybeNull
678
        @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Object class can never be passed.")
679
        public String getSuperClass(String internalName) {
UNCOV
680
            TypeDescription typeDescription = typePool.describe(internalName.replace('/', '.')).resolve();
×
UNCOV
681
            return typeDescription.isInterface()
×
682
                    ? null
UNCOV
683
                    : typeDescription.getSuperClass().asErasure().getInternalName();
×
684
        }
685
    }
686
}
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