Download it from repo.spring.io or Maven Central repositories (stable releases only):
repositories {
mavenCentral()
// maven { url 'https://repo.spring.io/milestone' }
// maven { url 'https://repo.spring.io/snapshot' }
}
dependencies {
testImplementation 'io.projectreactor.tools:blockhound:$LATEST_RELEASE'
// testImplementation 'io.projectreactor.tools:blockhound:$LATEST_MILESTONE'
// testImplementation 'io.projectreactor.tools:blockhound:$LATEST_SNAPSHOT'
}
Where:
$LATEST_RELEASE |
|
$LATEST_MILESTONE |
|
$LATEST_SNAPSHOT |
for JDK 13+, it is no longer allowed redefining native methods. So for the moment, as a temporary work around, please use the
-XX:+AllowRedefinitionToAddDeleteMethods
jvm argument:
Maven
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<argLine>-XX:+AllowRedefinitionToAddDeleteMethods</argLine>
</configuration>
</plugin>
Gradle
tasks.withType(Test).all {
if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_13)) {
jvmArgs += [
"-XX:+AllowRedefinitionToAddDeleteMethods"
]
}
}
When using BlockHound from a Tomcat webapp, do not embedd blockhound dependency within your webapp. Instead of that, just drop
the blockhound jar in the Tomcat shared "lib" directory.
If you are using Cargo
maven plugin, this can be done using a shared classpath
Here is an example using Cargo maven plugin:
<dependencies>
<dependency>
<groupId>io.projectreactor.tools</groupId>
<artifactId>blockhound</artifactId>
<version>(latest blockhound version)</version>
<scope>provided</scope>
</dependency>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven3-plugin</artifactId>
<version>1.10.4</version>
<configuration>
<container>
<containerId>tomcat9x</containerId>
<type>embedded</type>
<dependencies>
<dependency>
<groupId>io.projectreactor.tools</groupId>
<artifactId>blockhound</artifactId>
<classpath>shared</classpath>
</dependency>
</dependencies>
</container>
<deployables>
<deployable>
<type>war</type>
<location>${project.build.directory}/${project.build.finalName}.war</location>
<properties>
<context>/</context>
</properties>
</deployable>
</deployables>
</configuration>
</plugin>
</plugins>
</build>
...
BlockHound is a JVM agent. You need to "install" it before it starts detecting the issues:
BlockHound.install();
On install, it will discover all known integrations (see writing custom integrations for details) and perform a one time instrumentation (see how it works). The method is idempotent, you can call it multiple times.
The best place to put this line is before any code gets executed, e.g. @BeforeClass
, or static {}
block, or test listener.
BlockHound also supports some testing frameworks.
NB: it is highly recommended to add a dummy test with a well-known blocking call to ensure that it installed correctly.
Something like this will work:
Mono.delay(Duration.ofMillis(1))
.doOnNext(it -> {
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
})
.block(); // should throw an exception about Thread.sleep
If you can't change the application code, you can also activate BlockHound using the -javaagent: JVM option, something like this (you need at least version 1.0.7):
java -javaagent:BlockHound/agent/build/libs/agent.jar -jar my-application.jar
Notice that when using JPMS, for the moment BlockHound needs to be installed using -javaavant
JVM option.
You can further customize Blockhound's behavior, see customization.