9
9
import net .bytebuddy .agent .Installer ;
10
10
11
11
import java .lang .instrument .Instrumentation ;
12
+ import java .util .List ;
12
13
13
14
import static org .mockito .internal .util .StringUtil .join ;
14
15
15
16
public class PremainAttachAccess {
16
17
18
+ private static volatile Instrumentation inst ;
19
+
17
20
public static Instrumentation getInstrumentation () {
21
+ if (inst != null ) {
22
+ return inst ;
23
+ }
18
24
// A Java agent is always added to the system class loader. If Mockito is executed from a
19
25
// different class loader we need to make sure to resolve the instrumentation instance
20
26
// from there, or fail the resolution, if this class does not exist on the system class
@@ -34,16 +40,41 @@ public static Instrumentation getInstrumentation() {
34
40
}
35
41
if (instrumentation == null ) {
36
42
if (ClassFileVersion .ofThisVm ().isAtLeast (ClassFileVersion .JAVA_V21 )) {
37
- // Cannot use `Plugins.getMockitoLogger().warn(...)` at this time due to a circular
38
- // dependency on `Plugins.registry`.
39
- // The `PluginRegistry` is not yet fully initialized (in `Plugins`), because it is
40
- // currently initializing the `MockMaker` which is a InlineByteBuddyMockMaker, and
41
- // it is later calling this method to access the instrumentation.
42
- System .err .println (
43
- "Mockito is currently self-attaching to enable the inline-mock-maker. This "
44
- + "will no longer work in future releases of the JDK. Please add Mockito as an agent to your "
45
- + "build as described in Mockito's documentation: "
46
- + "https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#0.3" );
43
+ boolean dynamicAgentLoading ;
44
+ try {
45
+ Object runtimeMXBean =
46
+ Class .forName ("java.lang.management.ManagementFactory" )
47
+ .getMethod ("getRuntimeMXBean" )
48
+ .invoke (null );
49
+ @ SuppressWarnings ("unchecked" )
50
+ List <String > arguments =
51
+ (List <String >)
52
+ runtimeMXBean
53
+ .getClass ()
54
+ .getMethod ("getInputArguments" )
55
+ .invoke (runtimeMXBean );
56
+ dynamicAgentLoading =
57
+ arguments .stream ()
58
+ .anyMatch (
59
+ argument ->
60
+ argument .contains (
61
+ "-XX:+EnableDynamicAgentLoading" ));
62
+ } catch (Exception ignored ) {
63
+ dynamicAgentLoading = false ;
64
+ }
65
+ if (!dynamicAgentLoading ) {
66
+ // Cannot use `Plugins.getMockitoLogger().warn(...)` at this time due to a
67
+ // circular dependency on `Plugins.registry`.
68
+ // The `PluginRegistry` is not yet fully initialized (in `Plugins`), because it
69
+ // is currently initializing the `MockMaker` which is a
70
+ // InlineByteBuddyMockMaker, and it is later calling this
71
+ // method to access the instrumentation.
72
+ System .err .println (
73
+ "Mockito is currently self-attaching to enable the inline-mock-maker. This "
74
+ + "will no longer work in future releases of the JDK. Please add Mockito as an agent to your "
75
+ + "build as described in Mockito's documentation: "
76
+ + "https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#0.3" );
77
+ }
47
78
}
48
79
// Attempt to dynamically attach, as a last resort.
49
80
instrumentation = ByteBuddyAgent .install ();
@@ -55,6 +86,7 @@ public static Instrumentation getInstrumentation() {
55
86
"" ,
56
87
"You cannot use this mock maker on this VM" ));
57
88
}
89
+ inst = instrumentation ;
58
90
return instrumentation ;
59
91
}
60
92
0 commit comments