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

raphw / byte-buddy / #801

27 Oct 2025 09:37AM UTC coverage: 84.715% (-0.4%) from 85.118%
#801

push

raphw
Fix imports.

29586 of 34924 relevant lines covered (84.72%)

0.85 hits per line

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

98.95
/byte-buddy-dep/src/main/java/net/bytebuddy/build/AccessControllerPlugin.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.build;
17

18
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19
import net.bytebuddy.asm.AsmVisitorWrapper;
20
import net.bytebuddy.description.method.MethodDescription;
21
import net.bytebuddy.description.modifier.FieldManifestation;
22
import net.bytebuddy.description.modifier.Ownership;
23
import net.bytebuddy.description.modifier.Visibility;
24
import net.bytebuddy.description.type.TypeDefinition;
25
import net.bytebuddy.description.type.TypeDescription;
26
import net.bytebuddy.dynamic.ClassFileLocator;
27
import net.bytebuddy.dynamic.DynamicType;
28
import net.bytebuddy.implementation.Implementation;
29
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
30
import net.bytebuddy.implementation.bytecode.StackSize;
31
import net.bytebuddy.pool.TypePool;
32
import net.bytebuddy.utility.JavaType;
33
import net.bytebuddy.utility.OpenedClassReader;
34
import net.bytebuddy.utility.nullability.MaybeNull;
35
import org.objectweb.asm.Label;
36
import org.objectweb.asm.MethodVisitor;
37
import org.objectweb.asm.Opcodes;
38
import org.objectweb.asm.Type;
39

40
import java.lang.annotation.Documented;
41
import java.lang.annotation.ElementType;
42
import java.lang.annotation.Retention;
43
import java.lang.annotation.RetentionPolicy;
44
import java.lang.annotation.Target;
45
import java.security.Permission;
46
import java.security.PrivilegedAction;
47
import java.security.PrivilegedExceptionAction;
48
import java.util.Collections;
49
import java.util.HashMap;
50
import java.util.Map;
51

52
import static net.bytebuddy.matcher.ElementMatchers.declaresMethod;
53
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
54
import static net.bytebuddy.matcher.ElementMatchers.named;
55

56
/**
57
 * A build tool plugin that instruments methods to dispatch to methods {@code java.security.AccessController} with equal signature.
58
 * This can be useful to avoid using types from the {@code java.security} package which were deprecated for removal in Java 17.
59
 * Annotated methods are dispatched to the JVM's access controller only if this type is available on the current VM, and if no system
60
 * property is added and set to disable such dispatch. In the process, {@code java.security.AccessControlContext} is represented by
61
 * {@link Object}.
62
 */
63
@HashCodeAndEqualsPlugin.Enhance
64
public class AccessControllerPlugin extends Plugin.ForElementMatcher implements Plugin.Factory {
65

66
    /**
67
     * The binary name of {@code java.security.AccessController}.
68
     */
69
    private static final String ACCESS_CONTROLLER = "java.security.AccessController";
70

71
    /**
72
     * The name of the generated field.
73
     */
74
    private static final String NAME = "ACCESS_CONTROLLER";
75

76
    /**
77
     * An empty array to create frames without additional allocation.
78
     */
79
    private static final Object[] EMPTY = new Object[0];
1✔
80

81
    /**
82
     * A map to all signatures of {@code java.security.AccessController} from a signature that does not contain any
83
     * types that are deprecated for removal.
84
     */
85
    private static final Map<MethodDescription.SignatureToken, MethodDescription.SignatureToken> SIGNATURES;
86

87
    /*
88
     * Adds all relevant access controller signatures to validating collection.
89
     */
90
    static {
91
        SIGNATURES = new HashMap<MethodDescription.SignatureToken, MethodDescription.SignatureToken>();
1✔
92
        SIGNATURES.put(new MethodDescription.SignatureToken("doPrivileged",
1✔
93
                TypeDescription.ForLoadedType.of(Object.class),
1✔
94
                TypeDescription.ForLoadedType.of(PrivilegedAction.class)), new MethodDescription.SignatureToken("doPrivileged",
1✔
95
                TypeDescription.ForLoadedType.of(Object.class),
1✔
96
                TypeDescription.ForLoadedType.of(PrivilegedAction.class)));
1✔
97
        SIGNATURES.put(new MethodDescription.SignatureToken("doPrivilegedWithCombiner",
1✔
98
                TypeDescription.ForLoadedType.of(Object.class),
1✔
99
                TypeDescription.ForLoadedType.of(PrivilegedAction.class)), new MethodDescription.SignatureToken("doPrivilegedWithCombiner",
1✔
100
                TypeDescription.ForLoadedType.of(Object.class),
1✔
101
                TypeDescription.ForLoadedType.of(PrivilegedAction.class)));
1✔
102
        SIGNATURES.put(new MethodDescription.SignatureToken("doPrivileged",
1✔
103
                TypeDescription.ForLoadedType.of(Object.class),
1✔
104
                TypeDescription.ForLoadedType.of(PrivilegedAction.class),
1✔
105
                TypeDescription.ForLoadedType.of(Object.class)), new MethodDescription.SignatureToken("doPrivileged",
1✔
106
                TypeDescription.ForLoadedType.of(Object.class),
1✔
107
                TypeDescription.ForLoadedType.of(PrivilegedAction.class),
1✔
108
                JavaType.ACCESS_CONTROL_CONTEXT.getTypeStub()));
1✔
109
        SIGNATURES.put(new MethodDescription.SignatureToken("doPrivileged",
1✔
110
                TypeDescription.ForLoadedType.of(Object.class),
1✔
111
                TypeDescription.ForLoadedType.of(PrivilegedAction.class),
1✔
112
                TypeDescription.ForLoadedType.of(Object.class),
1✔
113
                TypeDescription.ForLoadedType.of(Permission[].class)), new MethodDescription.SignatureToken("doPrivileged",
1✔
114
                TypeDescription.ForLoadedType.of(Object.class),
1✔
115
                TypeDescription.ForLoadedType.of(PrivilegedAction.class),
1✔
116
                JavaType.ACCESS_CONTROL_CONTEXT.getTypeStub(),
1✔
117
                TypeDescription.ForLoadedType.of(Permission[].class)));
1✔
118
        SIGNATURES.put(new MethodDescription.SignatureToken("doPrivilegedWithCombiner",
1✔
119
                TypeDescription.ForLoadedType.of(Object.class),
1✔
120
                TypeDescription.ForLoadedType.of(PrivilegedAction.class),
1✔
121
                TypeDescription.ForLoadedType.of(Object.class),
1✔
122
                TypeDescription.ForLoadedType.of(Permission[].class)), new MethodDescription.SignatureToken("doPrivilegedWithCombiner",
1✔
123
                TypeDescription.ForLoadedType.of(Object.class),
1✔
124
                TypeDescription.ForLoadedType.of(PrivilegedAction.class),
1✔
125
                JavaType.ACCESS_CONTROL_CONTEXT.getTypeStub(),
1✔
126
                TypeDescription.ForLoadedType.of(Permission[].class)));
1✔
127
        SIGNATURES.put(new MethodDescription.SignatureToken("doPrivileged",
1✔
128
                TypeDescription.ForLoadedType.of(Object.class),
1✔
129
                TypeDescription.ForLoadedType.of(PrivilegedExceptionAction.class)), new MethodDescription.SignatureToken("doPrivileged",
1✔
130
                TypeDescription.ForLoadedType.of(Object.class),
1✔
131
                TypeDescription.ForLoadedType.of(PrivilegedExceptionAction.class)));
1✔
132
        SIGNATURES.put(new MethodDescription.SignatureToken("doPrivilegedWithCombiner",
1✔
133
                TypeDescription.ForLoadedType.of(Object.class),
1✔
134
                TypeDescription.ForLoadedType.of(PrivilegedExceptionAction.class)), new MethodDescription.SignatureToken("doPrivilegedWithCombiner",
1✔
135
                TypeDescription.ForLoadedType.of(Object.class),
1✔
136
                TypeDescription.ForLoadedType.of(PrivilegedExceptionAction.class)));
1✔
137
        SIGNATURES.put(new MethodDescription.SignatureToken("doPrivileged",
1✔
138
                TypeDescription.ForLoadedType.of(Object.class),
1✔
139
                TypeDescription.ForLoadedType.of(PrivilegedExceptionAction.class),
1✔
140
                TypeDescription.ForLoadedType.of(Object.class)), new MethodDescription.SignatureToken("doPrivileged",
1✔
141
                TypeDescription.ForLoadedType.of(Object.class),
1✔
142
                TypeDescription.ForLoadedType.of(PrivilegedExceptionAction.class),
1✔
143
                JavaType.ACCESS_CONTROL_CONTEXT.getTypeStub()));
1✔
144
        SIGNATURES.put(new MethodDescription.SignatureToken("doPrivileged",
1✔
145
                TypeDescription.ForLoadedType.of(Object.class),
1✔
146
                TypeDescription.ForLoadedType.of(PrivilegedExceptionAction.class),
1✔
147
                TypeDescription.ForLoadedType.of(Object.class),
1✔
148
                TypeDescription.ForLoadedType.of(Permission[].class)), new MethodDescription.SignatureToken("doPrivileged",
1✔
149
                TypeDescription.ForLoadedType.of(Object.class),
1✔
150
                TypeDescription.ForLoadedType.of(PrivilegedExceptionAction.class),
1✔
151
                JavaType.ACCESS_CONTROL_CONTEXT.getTypeStub(),
1✔
152
                TypeDescription.ForLoadedType.of(Permission[].class)));
1✔
153
        SIGNATURES.put(new MethodDescription.SignatureToken("doPrivilegedWithCombiner",
1✔
154
                TypeDescription.ForLoadedType.of(Object.class),
1✔
155
                TypeDescription.ForLoadedType.of(PrivilegedExceptionAction.class),
1✔
156
                TypeDescription.ForLoadedType.of(Object.class),
1✔
157
                TypeDescription.ForLoadedType.of(Permission[].class)), new MethodDescription.SignatureToken("doPrivilegedWithCombiner",
1✔
158
                TypeDescription.ForLoadedType.of(Object.class),
1✔
159
                TypeDescription.ForLoadedType.of(PrivilegedExceptionAction.class),
1✔
160
                JavaType.ACCESS_CONTROL_CONTEXT.getTypeStub(),
1✔
161
                TypeDescription.ForLoadedType.of(Permission[].class)));
1✔
162
        SIGNATURES.put(new MethodDescription.SignatureToken("getContext",
1✔
163
                TypeDescription.ForLoadedType.of(Object.class)), new MethodDescription.SignatureToken("getContext",
1✔
164
                JavaType.ACCESS_CONTROL_CONTEXT.getTypeStub()));
1✔
165
        SIGNATURES.put(new MethodDescription.SignatureToken("checkPermission",
1✔
166
                TypeDescription.ForLoadedType.of(void.class),
1✔
167
                TypeDescription.ForLoadedType.of(Permission.class)), new MethodDescription.SignatureToken("checkPermission",
1✔
168
                TypeDescription.ForLoadedType.of(void.class),
1✔
169
                TypeDescription.ForLoadedType.of(Permission.class)));
1✔
170
    }
1✔
171

172
    /**
173
     * The property to control if the access controller should be used even
174
     * if available or {@code null} if such a property should not be available.
175
     */
176
    @MaybeNull
177
    @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY)
178
    private final String property;
179

180
    /**
181
     * Creates a new plugin to weave access controller dispatches without
182
     * a property to allow for disabling the access controller handling.
183
     */
184
    public AccessControllerPlugin() {
185
        this(null);
1✔
186
    }
1✔
187

188
    /**
189
     * Creates a new plugin to weave access controller dispatches.
190
     *
191
     * @param property The property to control if the access controller should be used even
192
     *                 if available or {@code null} if such a property should not be available.
193
     */
194
    @UsingReflection.Priority(Integer.MAX_VALUE)
195
    public AccessControllerPlugin(@MaybeNull String property) {
196
        super(declaresMethod(isAnnotatedWith(Enhance.class)));
1✔
197
        this.property = property;
1✔
198
    }
1✔
199

200
    /**
201
     * {@inheritDoc}
202
     */
203
    public Plugin make() {
204
        return this;
×
205
    }
206

207
    /**
208
     * {@inheritDoc}
209
     */
210
    @SuppressFBWarnings(value = "SBSC_USE_STRINGBUFFER_CONCATENATION", justification = "Collision is unlikely and buffer overhead not justified.")
211
    public DynamicType.Builder<?> apply(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassFileLocator classFileLocator) {
212
        String name = NAME;
1✔
213
        while (!typeDescription.getDeclaredFields().filter(named(name)).isEmpty()) {
1✔
214
            name += "$";
1✔
215
        }
216
        return builder
1✔
217
                .defineField(name, boolean.class, Visibility.PRIVATE, Ownership.STATIC, FieldManifestation.FINAL)
1✔
218
                .visit(new AsmVisitorWrapper.ForDeclaredMethods().method(isAnnotatedWith(Enhance.class), new AccessControlWrapper(name)))
1✔
219
                .initializer(property == null
1✔
220
                        ? new Initializer.WithoutProperty(typeDescription, name)
221
                        : new Initializer.WithProperty(typeDescription, name, property));
222
    }
223

224
    /**
225
     * {@inheritDoc}
226
     */
227
    public void close() {
228
        /* do nothing */
229
    }
×
230

231
    /**
232
     * A byte code appender to create an initializer segment that determines if
233
     * the {@code java.security.AccessController} is available.
234
     */
235
    @HashCodeAndEqualsPlugin.Enhance
236
    protected abstract static class Initializer implements ByteCodeAppender {
237

238
        /**
239
         * The instrumented type.
240
         */
241
        private final TypeDescription instrumentedType;
242

243
        /**
244
         * The name of the field to determine the use of access controller dispatch.
245
         */
246
        private final String name;
247

248
        /**
249
         * Creates a new initializer.
250
         *
251
         * @param instrumentedType The instrumented type.
252
         * @param name             The name of the field to determine the use of access controller dispatch.
253
         */
254
        protected Initializer(TypeDescription instrumentedType, String name) {
1✔
255
            this.instrumentedType = instrumentedType;
1✔
256
            this.name = name;
1✔
257
        }
1✔
258

259
        /**
260
         * {@inheritDoc}
261
         */
262
        public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) {
263
            Label start = new Label(), end = new Label(), classNotFound = new Label(), securityException = new Label(), complete = new Label();
1✔
264
            methodVisitor.visitTryCatchBlock(start, end, classNotFound, Type.getInternalName(ClassNotFoundException.class));
1✔
265
            methodVisitor.visitTryCatchBlock(start, end, securityException, Type.getInternalName(SecurityException.class));
1✔
266
            methodVisitor.visitLabel(start);
1✔
267
            methodVisitor.visitLdcInsn(ACCESS_CONTROLLER);
1✔
268
            methodVisitor.visitInsn(Opcodes.ICONST_0);
1✔
269
            methodVisitor.visitInsn(Opcodes.ACONST_NULL);
1✔
270
            methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
1✔
271
                    Type.getInternalName(Class.class),
1✔
272
                    "forName",
273
                    Type.getMethodDescriptor(Type.getType(Class.class),
1✔
274
                            Type.getType(String.class),
1✔
275
                            Type.getType(boolean.class),
1✔
276
                            Type.getType(ClassLoader.class)),
1✔
277
                    false);
278
            methodVisitor.visitInsn(Opcodes.POP);
1✔
279
            int size = onAccessController(methodVisitor);
1✔
280
            methodVisitor.visitFieldInsn(Opcodes.PUTSTATIC, instrumentedType.getInternalName(), name, Type.getDescriptor(boolean.class));
1✔
281
            methodVisitor.visitLabel(end);
1✔
282
            methodVisitor.visitJumpInsn(Opcodes.GOTO, complete);
1✔
283
            methodVisitor.visitLabel(classNotFound);
1✔
284
            implementationContext.getFrameGeneration().same1(methodVisitor,
1✔
285
                    TypeDescription.ForLoadedType.of(ClassNotFoundException.class),
1✔
286
                    Collections.<TypeDefinition>emptyList());
1✔
287
            methodVisitor.visitInsn(Opcodes.POP);
1✔
288
            methodVisitor.visitInsn(Opcodes.ICONST_0);
1✔
289
            methodVisitor.visitFieldInsn(Opcodes.PUTSTATIC, instrumentedType.getInternalName(), name, Type.getDescriptor(boolean.class));
1✔
290
            methodVisitor.visitJumpInsn(Opcodes.GOTO, complete);
1✔
291
            methodVisitor.visitLabel(securityException);
1✔
292
            implementationContext.getFrameGeneration().same1(methodVisitor,
1✔
293
                    TypeDescription.ForLoadedType.of(SecurityException.class),
1✔
294
                    Collections.<TypeDefinition>emptyList());
1✔
295
            methodVisitor.visitInsn(Opcodes.POP);
1✔
296
            methodVisitor.visitInsn(Opcodes.ICONST_1);
1✔
297
            methodVisitor.visitFieldInsn(Opcodes.PUTSTATIC, instrumentedType.getInternalName(), name, Type.getDescriptor(boolean.class));
1✔
298
            methodVisitor.visitLabel(complete);
1✔
299
            implementationContext.getFrameGeneration().same(methodVisitor, Collections.<TypeDefinition>emptyList());
1✔
300
            return new Size(Math.max(3, size), 0);
1✔
301
        }
302

303
        /**
304
         * Invoked to determine if the access controller should be used after the class was found.
305
         *
306
         * @param methodVisitor The method visitor to dispatch to.
307
         * @return The size of the stack required to implement the implemented dispatch.
308
         */
309
        protected abstract int onAccessController(MethodVisitor methodVisitor);
310

311
        /**
312
         * An initializer that uses a property to determine if the access controller should be actually used even if it is available.
313
         */
314
        @HashCodeAndEqualsPlugin.Enhance
315
        protected static class WithProperty extends Initializer {
316

317
            /**
318
             * The name of the property.
319
             */
320
            private final String property;
321

322
            /**
323
             * Creates an initializer that uses a property to determine if the access controller should be actually used even if it is available.
324
             *
325
             * @param instrumentedType The instrumented type.
326
             * @param name             The name of the field to determine the use of access controller dispatch.
327
             * @param property         The name of the property.
328
             */
329
            protected WithProperty(TypeDescription instrumentedType, String name, String property) {
330
                super(instrumentedType, name);
1✔
331
                this.property = property;
1✔
332
            }
1✔
333

334
            @Override
335
            protected int onAccessController(MethodVisitor methodVisitor) {
336
                methodVisitor.visitLdcInsn(property);
1✔
337
                methodVisitor.visitLdcInsn("true");
1✔
338
                methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
1✔
339
                        Type.getInternalName(System.class),
1✔
340
                        "getProperty",
341
                        Type.getMethodDescriptor(Type.getType(String.class), Type.getType(String.class), Type.getType(String.class)),
1✔
342
                        false);
343
                methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
1✔
344
                        Type.getInternalName(Boolean.class),
1✔
345
                        "parseBoolean",
346
                        Type.getMethodDescriptor(Type.getType(boolean.class), Type.getType(String.class)),
1✔
347
                        false);
348
                return 2;
1✔
349
            }
350
        }
351

352
        /**
353
         * An initializer that always uses the access controller if it is available.
354
         */
355
        @HashCodeAndEqualsPlugin.Enhance
356
        protected static class WithoutProperty extends Initializer {
357

358
            /**
359
             * Creates an initializer that always uses the access controller if it is available.
360
             *
361
             * @param instrumentedType The instrumented type.
362
             * @param name             The name of the field to determine the use of access controller dispatch.
363
             */
364
            protected WithoutProperty(TypeDescription instrumentedType, String name) {
365
                super(instrumentedType, name);
1✔
366
            }
1✔
367

368
            @Override
369
            protected int onAccessController(MethodVisitor methodVisitor) {
370
                methodVisitor.visitInsn(Opcodes.ICONST_1);
1✔
371
                return 1;
1✔
372
            }
373
        }
374
    }
375

376
    /**
377
     * An wrapper for a method that represents a method of {@code AccessController} which is weaved.
378
     */
379
    @HashCodeAndEqualsPlugin.Enhance
380
    protected static class AccessControlWrapper implements AsmVisitorWrapper.ForDeclaredMethods.MethodVisitorWrapper {
381

382
        /**
383
         * The name of the field.
384
         */
385
        private final String name;
386

387
        /**
388
         * Creates a new access control wrapper.
389
         *
390
         * @param name The name of the field.
391
         */
392
        protected AccessControlWrapper(String name) {
1✔
393
            this.name = name;
1✔
394
        }
1✔
395

396
        /**
397
         * {@inheritDoc}
398
         */
399
        public MethodVisitor wrap(TypeDescription instrumentedType,
400
                                  MethodDescription instrumentedMethod,
401
                                  MethodVisitor methodVisitor,
402
                                  Implementation.Context implementationContext,
403
                                  TypePool typePool,
404
                                  int writerFlags,
405
                                  int readerFlags) {
406
            MethodDescription.SignatureToken token = SIGNATURES.get(instrumentedMethod.asDefined().asSignatureToken());
1✔
407
            if (token == null) {
1✔
408
                throw new IllegalStateException(instrumentedMethod + " does not have a method with a matching signature in " + ACCESS_CONTROLLER);
1✔
409
            } else if (instrumentedMethod.isPublic() || instrumentedMethod.isProtected()) {
1✔
410
                throw new IllegalStateException(instrumentedMethod + " is either public or protected what is not permitted to avoid context leaks");
1✔
411
            }
412
            return new PrefixingMethodVisitor(methodVisitor,
1✔
413
                    instrumentedType,
414
                    token,
415
                    name,
416
                    instrumentedMethod.isStatic() ? 0 : 1,
1✔
417
                    implementationContext.getFrameGeneration());
1✔
418
        }
419

420
        /**
421
         * A method visitor to implement a weaved method to dispatch to an {@code java.security.AccessController}, if available.
422
         */
423
        protected static class PrefixingMethodVisitor extends MethodVisitor {
424

425
            /**
426
             * The instrumented type.
427
             */
428
            private final TypeDescription instrumentedType;
429

430
            /**
431
             * The target signature of the method declared by the JVM access controller.
432
             */
433
            private final MethodDescription.SignatureToken token;
434

435
            /**
436
             * The name of the field.
437
             */
438
            private final String name;
439

440
            /**
441
             * The base offset of the weaved method.
442
             */
443
            private final int offset;
444

445
            /**
446
             * Indicates the frame generation mode to apply.
447
             */
448
            private final Implementation.Context.FrameGeneration frameGeneration;
449

450
            /**
451
             * Creates a new prefixing method visitor.
452
             *
453
             * @param methodVisitor    The method visitor to write to.
454
             * @param instrumentedType The instrumented type.
455
             * @param token            The target signature of the method declared by the JVM access controller.
456
             * @param name             The name of the field.
457
             * @param offset           The base offset of the instrumented method.
458
             * @param frameGeneration  Indicates the frame generation mode to apply.
459
             */
460
            protected PrefixingMethodVisitor(MethodVisitor methodVisitor,
461
                                             TypeDescription instrumentedType,
462
                                             MethodDescription.SignatureToken token,
463
                                             String name,
464
                                             int offset,
465
                                             Implementation.Context.FrameGeneration frameGeneration) {
466
                super(OpenedClassReader.ASM_API, methodVisitor);
1✔
467
                this.instrumentedType = instrumentedType;
1✔
468
                this.token = token;
1✔
469
                this.name = name;
1✔
470
                this.offset = offset;
1✔
471
                this.frameGeneration = frameGeneration;
1✔
472
            }
1✔
473

474
            @Override
475
            public void visitCode() {
476
                mv.visitCode();
1✔
477
                mv.visitFieldInsn(Opcodes.GETSTATIC, instrumentedType.getInternalName(), name, Type.getDescriptor(boolean.class));
1✔
478
                Label label = new Label();
1✔
479
                mv.visitJumpInsn(Opcodes.IFEQ, label);
1✔
480
                int offset = this.offset;
1✔
481
                for (TypeDescription typeDescription : token.getParameterTypes()) {
1✔
482
                    mv.visitVarInsn(Type.getType(typeDescription.getDescriptor()).getOpcode(Opcodes.ILOAD), offset);
1✔
483
                    if (typeDescription.equals(JavaType.ACCESS_CONTROL_CONTEXT.getTypeStub())) {
1✔
484
                        mv.visitTypeInsn(Opcodes.CHECKCAST, typeDescription.getInternalName());
1✔
485
                    }
486
                    offset += typeDescription.getStackSize().getSize();
1✔
487
                }
1✔
488
                mv.visitMethodInsn(Opcodes.INVOKESTATIC,
1✔
489
                        ACCESS_CONTROLLER.replace('.', '/'),
1✔
490
                        token.getName(),
1✔
491
                        token.getDescriptor(),
1✔
492
                        false);
493
                mv.visitInsn(Type.getType(token.getReturnType().getDescriptor()).getOpcode(Opcodes.IRETURN));
1✔
494
                mv.visitLabel(label);
1✔
495
                frameGeneration.same(mv, token.getParameterTypes());
1✔
496
            }
1✔
497

498
            @Override
499
            public void visitMaxs(int stackSize, int localVariableLength) {
500
                mv.visitMaxs(Math.max(Math.max(StackSize.of(token.getParameterTypes()),
1✔
501
                        token.getReturnType().getStackSize().getSize()), stackSize), localVariableLength);
1✔
502
            }
1✔
503
        }
504
    }
505

506
    /**
507
     * Indicates that the annotated method represents a pseudo implementation of {@code java.security.AccessController}
508
     * which can be weaved to dispatch to the access controller if this is possible on the current VM and not explicitly
509
     * disabled on the current VM via a system property.
510
     */
511
    @Documented
512
    @Target(ElementType.METHOD)
513
    @Retention(RetentionPolicy.RUNTIME)
514
    public @interface Enhance {
515
        /* empty */
516
    }
517
}
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