8000 Avoid warning when dynamic attach is enabled with JVM flag (#3551) · mockito/mockito@cd4704a · GitHub
[go: up one dir, main page]

Skip to content

Commit cd4704a

Browse files
authored
Avoid warning when dynamic attach is enabled with JVM flag (#3551)
Fixes #3512
1 parent 3731b6b commit cd4704a

File tree

3 files changed

+61
-10
lines changed

3 files changed

+61
-10
lines changed

mockito-core/src/main/java/org/mockito/Mockito.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,11 @@
244244
* </plugin>
245245
* </code></pre>
246246
*
247+
* <p>
248+
* To enable support for dynamic attach, it is also possible to start a JVM with
249+
* <pre>-XX:+EnableDynamicAgentLoading</pre>. Do however note that, since this option is not standardized, any future
250+
* release of a JDK might prohibit this behaviour.
251+
*
247252
* <h3 id="1">1. <a class="meaningful_link" href="#verification" name="verification">Let's verify some behaviour!</a></h3>
248253
*
249254
* The following examples mock a List, because most people are familiar with the interface (such as the

mockito-core/src/main/java/org/mockito/internal/PremainAttachAccess.java

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,18 @@
99
import net.bytebuddy.agent.Installer;
1010

1111
import java.lang.instrument.Instrumentation;
12+
import java.util.List;
1213

1314
import static org.mockito.internal.util.StringUtil.join;
1415

1516
public class PremainAttachAccess {
1617

18+
private static volatile Instrumentation inst;
19+
1720
public static Instrumentation getInstrumentation() {
21+
if (inst != null) {
22+
return inst;
23+
}
1824
// A Java agent is always added to the system class loader. If Mockito is executed from a
1925
// different class loader we need to make sure to resolve the instrumentation instance
2026
// from there, or fail the resolution, if this class does not exist on the system class
@@ -34,16 +40,41 @@ public static Instrumentation getInstrumentation() {
3440
}
3541
if (instrumentation == null) {
3642
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+
}
4778
}
4879
// Attempt to dynamically attach, as a last resort.
4980
instrumentation = ByteBuddyAgent.install();
@@ -55,6 +86,7 @@ public static Instrumentation getInstrumentation() {
5586
"",
5687
"You cannot use this mock maker on this VM"));
5788
}
89+
inst = instrumentation;
5890
return instrumentation;
5991
}
6092

mockito-integration-tests/java-21-tests/build.gradle.kts

Lines changed: 14 additions & 0 deletions
70E5
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ tasks {
3232
// "-Djdk.instrument.traceUsage",
3333
)
3434
}
35+
failIfStdErrWarningOnDynamicallyLoadedAgent(this)
< 57AE /code>
3536
}
3637

3738
val testWithMockitoAgent by registering(Test::class) {
@@ -51,10 +52,23 @@ tasks {
5152
failIfStdErrWarningOnDynamicallyLoadedAgent(this)
5253
}
5354

55+
val testWithEnableDynamicAgentLoading by registering(Test::class) {
56+
if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21)) {
57+
enabled = false
58+
} else {
59+
jvmArgs(
60+
"-XX:+EnableDynamicAgentLoading",
61+
// "-Djdk.instrument.traceUsage",
62+
)
63+
}
64+
failIfStdErrWarningOnDynamicallyLoadedAgent(this)
65+
}
66+
5467
named<Test>("test") {
5568
dependsOn(
5669
testWithMockitoAgent,
5770
testWithBytebuddyAgent,
71+
testWithEnableDynamicAgentLoading,
5872
)
5973
isEnabled = JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21)
6074

0 commit comments

Comments
 (0)
0