Coder Social home page Coder Social logo

blockhound's Introduction

Reactor Project

Join the chat at https://gitter.im/reactor/reactor

Download

Starting from 3.0, Reactor is now organized into multiple projects:

A set of compatible versions for all these projects is curated under a BOM ("Bill of Materials") hosted under this very repository.

Using the BOM with Maven

In Maven, you need to import the bom first:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-bom</artifactId>
            <version>2024.0.0-M1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Notice we use the <dependencyManagement> section and the import scope.

Next, add your dependencies to the relevant reactor projects as usual, except without a <version>:

<dependencies>
    <dependency>
        <groupId>io.projectreactor</groupId>
        <artifactId>reactor-core</artifactId>
    </dependency>
    <dependency>
        <groupId>io.projectreactor</groupId>
        <artifactId>reactor-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Using the BOM with Gradle

Gradle 5.0+

Use the platform keyword to import the Maven BOM within the dependencies block, then add dependencies to your project without a version number.

dependencies {
     // import BOM
     implementation platform('io.projectreactor:reactor-bom:2024.0.0-M1')

     // add dependencies without a version number
     implementation 'io.projectreactor:reactor-core'
}

Gradle 4.x and earlier

Gradle versions prior to 5.0 have no core support for Maven BOMs, but you can use Spring's gradle-dependency-management plugin.

First, apply the plugin from Gradle Plugin Portal (check and change the version if a new one has been released):

plugins {
    id "io.spring.dependency-management" version "1.0.11.RELEASE"
}

Then use it to import the BOM:

dependencyManagement {
     imports {
          mavenBom "io.projectreactor:reactor-bom:2024.0.0-M1"
     }
}

Then add a dependency to your project without a version number:

dependencies {
     compile 'io.projectreactor:reactor-core'
}

BOM Versioning Scheme

The BOM can be imported in Maven, which will provide a set of default artifact versions to use whenever the corresponding dependency is added to a pom without an explicitly provided version.

As the different artifacts versions are not necessarily aligned, the BOM represents a release train with an heterogeneous range of versions that are curated to work together. The artifact version follows the YYYY.MINOR.MICRO-QUALIFIER scheme since Europium, where:

  • YYYY is the year of the first GA release in a given release cycle (like 3.4.0 for 3.4.x)
  • .MINOR is a 0-based number incrementing with each new release cycle ** in the case of the BOM it allows discerning between release cycles in case two get first released the same year
  • .PATCH is a 0-based number incrementing with each service release
  • -QUALIFIER is a textual qualifier, which is omitted in the case of GA releases (see below)

On top of the artifact version, each release train has an associated codename, a chemical name from the Periodic Table of Elements in growing alphabetical order, for reference in discussions.

So far, the release trains code names are:

  • Aluminium for the 3.0.x generation of Reactor-Core (๐Ÿ’ก)
  • Bismuth for the 3.1.x generation (๐Ÿ’ก)
  • Californium for the 3.2.x generation (๐Ÿ’ก)
  • Dysprosium for the 3.3.x generation (๐Ÿ’ก)
  • Europium (2020.0) for the 3.4.x generation (๐Ÿ’ก)

NOTE: Up until Dysprosium, the BOM was versioned using a release train scheme with a codename followed by a qualifier, and the qualifiers were slightly different. For example: Aluminium-RELEASE (first GA release, would now be something like YYYY.0.0), Bismuth-M1, Californium-SR1 (service release would now be something like YYYY.0.1), Dysprosium-RC1, Dysprosium-BUILD-SNAPSHOT (after each patch, we'd go back to the same snapshot version. would now be something like YYYY.0.X-SNAPSHOT so we get 1 snapshot per PATCH).

Contributing, Community / Support

license

As hinted above, this repository is for hosting the BOM and for transverse issues only. Most of the time, if you're looking to open an issue or a PR, it should be done in a more specific repository corresponding to one of the actual artifacts.

All projects follow the same detailed contributing guidelines which you can find here.

This document also give some ways you can get answers to your questions.

Documentation

Detail of Projects

Reactor Core

Reactor Core

Reactive foundations for apps and frameworks and reactive extensions inspired API with Mono (1 element) and Flux (n elements) types

Reactor Netty

Reactor Netty

TCP and HTTP client and server.

Reactor Addons

Reactor Addons

Extra projects adding features to reactor:

Snapshot Artifacts

While Stable Releases are synchronized with Maven Central, fresh snapshot and milestone artifacts are provided in the repo.spring.io repositories.

To add this repo to your Maven build, add it to the <repositories> section like the following:

<repositories>
	<repository>
	    <id>spring-snapshot</id>
	    <name>Spring Snapshot Repository</name>
	    <url>https://repo.spring.io/snapshot</url>
	    <snapshots>
	        <enabled>true</enabled>
	    </snapshots>
	</repository>
</repositories>

To add it to your Gradle build, use the repositories configuration like this:

repositories {
	maven { url 'https://repo.spring.io/libs-snapshot' }
	mavenCentral()
}

You should then be able to import a -SNAPSHOT version of the BOM, like 2020.0.{NUMBER}-SNAPSHOT for the snapshot of the {NUMBER}th service release of 2020.0 (Europium).

Sponsored by VMware

blockhound's People

Contributors

62mkv avatar badbond avatar bennett-lynch avatar bhchandra avatar bsideup avatar daggerok avatar dependabot-preview[bot] avatar dependabot[bot] avatar dsibilio avatar jrehwaldt avatar lhotari avatar mfvanek avatar nickcaballero avatar pderop avatar philsttr avatar sbrannen avatar simonbasle avatar smaldini avatar szpak avatar tarungulati1988 avatar viliam-durina avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blockhound's Issues

Provide API or document how to allow/disallow blocking inside constructors

There is no guidance I could find on how to allow/disallow blocking in a constructor or static initializer. There is one test that shows how to do it for a static initializer but it would be nicer if it was easier to find. One option could be a dedicated method, e.g. allowBlockingCallsInsideConstructor(String classname), or otherwise provide guidance in the Javadoc on allowBlockingCallsInside and a mention on the Customizations page.

Cloud Foundry Java Buildpack installation throws IllegalStateException: No compatible attachment provider is available.

Added the dependency in pom.xml, added the BlockHound.install() in my main

Running locally works everything.

Pushed the application to cloud foundry (java buildpack)

Getting the error:

2020-10-14T13:35:48.471+02:00 [APP/PROC/WEB/0] [ERR] Exception in thread "main" java.lang.reflect.InvocationTargetException
2020-10-14T13:35:48.473+02:00 [APP/PROC/WEB/0] [ERR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2020-10-14T13:35:48.473+02:00 [APP/PROC/WEB/0] [ERR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
2020-10-14T13:35:48.473+02:00 [APP/PROC/WEB/0] [ERR] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
2020-10-14T13:35:48.474+02:00 [APP/PROC/WEB/0] [ERR] at java.base/java.lang.reflect.Method.invoke(Unknown Source)
2020-10-14T13:35:48.474+02:00 [APP/PROC/WEB/0] [ERR] at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
2020-10-14T13:35:48.474+02:00 [APP/PROC/WEB/0] [ERR] at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
2020-10-14T13:35:48.474+02:00 [APP/PROC/WEB/0] [ERR] at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
2020-10-14T13:35:48.475+02:00 [APP/PROC/WEB/0] [ERR] at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
2020-10-14T13:35:48.476+02:00 [APP/PROC/WEB/0] [ERR] Caused by: java.lang.RuntimeException: java.lang.IllegalStateException: No compatible attachment provider is available
2020-10-14T13:35:48.476+02:00 [APP/PROC/WEB/0] [ERR] at reactor.blockhound.BlockHound$Builder.install(BlockHound.java:398)
2020-10-14T13:35:48.476+02:00 [APP/PROC/WEB/0] [ERR] at reactor.blockhound.BlockHound.install(BlockHound.java:94)
2020-10-14T13:35:48.477+02:00 [APP/PROC/WEB/0] [ERR] at com.avsar.edu.demo.DemoApplication.main(DemoApplication.java:11)
2020-10-14T13:35:48.477+02:00 [APP/PROC/WEB/0] [ERR] ... 8 more
2020-10-14T13:35:48.477+02:00 [APP/PROC/WEB/0] [ERR] Caused by: java.lang.IllegalStateException: No compatible attachment provider is available
2020-10-14T13:35:48.477+02:00 [APP/PROC/WEB/0] [ERR] at reactor.blockhound.shaded.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:602)
2020-10-14T13:35:48.477+02:00 [APP/PROC/WEB/0] [ERR] at reactor.blockhound.shaded.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:586)
2020-10-14T13:35:48.477+02:00 [APP/PROC/WEB/0] [ERR] at reactor.blockhound.shaded.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:538)
2020-10-14T13:35:48.477+02:00 [APP/PROC/WEB/0] [ERR] at reactor.blockhound.shaded.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:515)
2020-10-14T13:35:48.477+02:00 [APP/PROC/WEB/0] [ERR] at reactor.blockhound.BlockHound$Builder.install(BlockHound.java:370)

Manifest looks like this:

---
applications:
  - name: blockhound-demo-app
    path: target/demo-0.0.1-SNAPSHOT.jar
    env:
      JBP_CONFIG_OPEN_JDK_JRE: '{ jre: { version: 11.+ }}'

Read in the internet about --javaagent options etc. Is this expected behaviour is my build pack not matching BlockHound?

Thanks
Emre

IllegalMonitorStateException in ReentrantLock$Sync.tryRelease on executor shutdown

Working on JMH in #35 I have encountered an exception thrown on an executor service shutdown if ReactorThreadFactory is used with rejectBlocking: false (and daemon: false in that case):

OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
result
java.lang.IllegalMonitorStateException
	at java.base/java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:149)
	at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1302)
	at java.base/java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:439)
	at java.base/java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:440)
	at java.base/java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1054)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1114)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)

It occurs only with BlockHound installed. Sample code to produce that result:

public class ReproduceIllegalMonitorStateException {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ThreadFactory blockingUnfriendlyThreadFactory = new ReactorThreadFactory("blocking-unfriendly", new AtomicLong(), false, true,
                (t, e) -> e.printStackTrace());
        ExecutorService executor = Executors.newSingleThreadExecutor(blockingUnfriendlyThreadFactory);;
        try {
            BlockHound.install();
            System.out.println(executor.submit(() -> "result").get());
        } finally {
            executor.shutdown(); //fails with non daemon thread with "java.lang.IllegalMonitorStateException" on "ReentrantLock$Sync.tryRelease()"
        }
    }
}

Make Thread predicate configurable

To improve the reactive interop, we should be able to mark custom threads as "non-blocking", e.g. Threads started by Cassandra driver.

The API draft:

BlockHound.builder()
    .threadPredicate(thread -> ...)
    .install();

How to integrate with Akka?

Hi @bsideup ,

I am trying to integrate blockhound for akka actors. I am running example code from your blog - https://bsideup.github.io/posts/blockhound_with_akka/

When I run this code I get following blocking calls reported -

	at esw.actor.ActorClass.lambda$main$2(ActorClass.java:32)
	at reactor.blockhound.BlockHound$Builder.lambda$install$8(BlockHound.java:382)
	at reactor.blockhound.BlockHoundRuntime.checkBlocking(BlockHoundRuntime.java:89)
	at java.base/jdk.internal.misc.Unsafe.park(Unsafe.java)
	at java.base/java.util.concurrent.locks.LockSupport.park(LockSupport.java:194)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1628)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)
java.lang.Exception: java.io.FileInputStream#readBytes
	at esw.actor.ActorClass.lambda$main$2(ActorClass.java:32)
	at reactor.blockhound.BlockHound$Builder.lambda$install$8(BlockHound.java:382)
	at reactor.blockhound.BlockHoundRuntime.checkBlocking(BlockHoundRuntime.java:89)
	at java.base/java.io.FileInputStream.readBytes(FileInputStream.java)
	at java.base/java.io.FileInputStream.read(FileInputStream.java:279)
	at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
	at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
	at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
	at java.base/java.io.InputStreamReader.read(InputStreamReader.java:185)
	at java.base/java.io.BufferedReader.fill(BufferedReader.java:161)
	at java.base/java.io.BufferedReader.read(BufferedReader.java:182)
	at java.base/java.io.StreamTokenizer.read(StreamTokenizer.java:500)
	at java.base/java.io.StreamTokenizer.nextToken(StreamTokenizer.java:544)
	at java.base/sun.security.provider.PolicyParser.read(PolicyParser.java:181)
	at java.base/sun.security.provider.PolicyFile.init(PolicyFile.java:514)
	at java.base/sun.security.provider.PolicyFile$3.run(PolicyFile.java:358)
	at java.base/sun.security.provider.PolicyFile$3.run(PolicyFile.java:355)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/sun.security.provider.PolicyFile.initPolicyFile(PolicyFile.java:355)
	at java.base/sun.security.provider.PolicyFile.init(PolicyFile.java:345)
	at java.base/sun.security.provider.PolicyFile.<init>(PolicyFile.java:298)
	at java.base/java.security.Policy.loadPolicyProvider(Policy.java:207)
	at java.base/java.security.Policy.getPolicyNoCheck(Policy.java:178)
	at java.base/java.security.ProtectionDomain.implies(ProtectionDomain.java:321)
	at java.base/java.security.ProtectionDomain.impliesWithAltFilePerm(ProtectionDomain.java:353)
	at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:450)
	at java.base/java.security.AccessController.checkPermission(AccessController.java:895)
	at ch.qos.logback.core.util.Loader$1.run(Loader.java:48)
	at ch.qos.logback.core.util.Loader$1.run(Loader.java:45)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at ch.qos.logback.core.util.Loader.<clinit>(Loader.java:45)
	at ch.qos.logback.classic.util.ContextInitializer.findURLOfDefaultConfigurationFile(ContextInitializer.java:119)
	at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:148)
	at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)
	at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:55)
	at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
	at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
	at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:417)
	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:362)
	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:388)
	at akka.actor.typed.internal.adapter.ActorSystemAdapter.<init>(ActorSystemAdapter.scala:90)
	at akka.actor.typed.internal.adapter.ActorSystemAdapter$AdapterExtension.<init>(ActorSystemAdapter.scala:126)
	at akka.actor.typed.internal.adapter.ActorSystemAdapter$AdapterExtension$.createExtension(ActorSystemAdapter.scala:133)
	at akka.actor.typed.internal.adapter.ActorSystemAdapter$AdapterExtension$.createExtension(ActorSystemAdapter.scala:129)
	at akka.actor.ActorSystemImpl.registerExtension(ActorSystem.scala:1159)
	at akka.actor.ExtensionId.apply(Extension.scala:78)
	at akka.actor.ExtensionId.apply$(Extension.scala:77)
	at akka.actor.typed.internal.adapter.ActorSystemAdapter$AdapterExtension$.apply(ActorSystemAdapter.scala:129)
	at akka.actor.typed.internal.adapter.ActorSystemAdapter$.apply(ActorSystemAdapter.scala:122)
	at akka.actor.typed.internal.adapter.ActorContextAdapter.<init>(ActorContextAdapter.scala:59)
	at akka.actor.typed.internal.adapter.ActorAdapter.ctx(ActorAdapter.scala:66)
	at akka.actor.typed.internal.adapter.ActorAdapter.preStart(ActorAdapter.scala:244)
	at akka.actor.Actor.aroundPreStart(Actor.scala:545)
	at akka.actor.Actor.aroundPreStart$(Actor.scala:545)
	at akka.actor.typed.internal.adapter.ActorAdapter.aroundPreStart(ActorAdapter.scala:56)
	at akka.actor.ActorCell.create(ActorCell.scala:637)
	at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:509)
	at akka.actor.ActorCell.systemInvoke(ActorCell.scala:531)
	at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:294)
	at akka.dispatch.Mailbox.run(Mailbox.scala:229)
	at akka.dispatch.Mailbox.exec(Mailbox.scala:242)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)

This stack trace shows so many blocking calls which are internal to akka implementation. I am only interested in detecting blocking calls in my actor code.

As per akka 2.6 documentation internal calls of akka use internal dispatcher not default dispatcher. So I modified nonBlockingThreadPredicate to monitor only default dispatcher thread -> thread.getName().contains("greeter-akka.actor.default-dispatcher"). Still I am getting all internal blocking calls reported. I have attached my code below.

package esw.actor;

import akka.actor.typed.ActorSystem;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.Behaviors;
import reactor.blockhound.BlockHound;

public class ActorClass {

    static final Behavior<String> behavior = Behaviors.receive((ctx, who) -> {
        if ("Blocking call".equals(who)) {
           Thread.sleep(2000);
        }

        System.out.println("Hello, " + who);

        return Behaviors.same();
    });

    public static void main(String[] args) throws Exception {
        BlockHound.install(builder -> {
            builder.nonBlockingThreadPredicate(p -> {
                return p.or(thread -> thread.getName().contains("greeter-akka.actor.default-dispatcher"));
            });
            builder.disallowBlockingCallsInside(
                    "akka.dispatch.MonitorableThreadFactory.AkkaForkJoinWorkerThread",
                    "execute"
            );
            builder.allowBlockingCallsInside("java.io.PrintStream", "println");
            builder.allowBlockingCallsInside("jdk.internal.misc.Unsafe", "park");
            builder.blockingMethodCallback(m -> {
                new Exception(m.toString()).printStackTrace();
            });
        });
        System.out.println("starting");
        var greeter = ActorSystem.create(behavior, "greeter");

        greeter.tell("Akka");
        greeter.tell("Java");
        greeter.tell("Blocking call");

        Thread.currentThread().join();
    }
}
  1. Is there any way to bypass akka internal blocking calls and only focus on my actor code?
  2. What does this snippet is for builder.disallowBlockingCallsInside( "akka.dispatch.MonitorableThreadFactory.AkkaForkJoinWorkerThread", "execute" );

java.lang.UnsatisfiedLinkError: reactor.blockhound.BlockHoundRuntime.isBlocking()Z

Trying to add my own "blocking" method in the JMH tests I've encountered:

java.lang.UnsatisfiedLinkError: reactor.blockhound.BlockHoundRuntime.isBlocking()Z

	at reactor.blockhound.BlockHoundRuntime.isBlocking(Native Method)
	at reactor.blockhound.BlockHoundRuntime.checkBlocking(BlockHoundRuntime.java:42)
	at com.example.Blocking.block(Blocking.java)
	at com.example.Grrr2Test.shouldAllowToDefineCustomBlockingMethod(Grrr2Test.java:122)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...

(execution of JUnit test (next to already existing com.example tests) from Idea).

To a builder configuration I add builder.markAsBlocking(Blocking.class, "block", "()V"); and call that method in JUnit test (or JMH test).

There could be a problem with a visibility of that class by the agent, but in that case the problem will also arise in real-life usage with own blocking methods. However, probably not too many projects will be affected (adding extra blocking methods from Java classes works - unless they are final - then they are silently ignored).

UUID.randomUUID() is detected as blocking, any replacement?

hi, I use blockhound in Env: Spring Cloud Gateway, the scenario is that each response need to generate to UUID, I use UUID.randomUUID(), but the Blockhound is warning it is blocking call! Any good suggestion is appreciated!
Thanks

Stack trace:
at java.io.FileInputStream.readBytes(FileInputStream.java)
at java.io.FileInputStream.read(FileInputStream.java:255)
at sun.security.provider.NativePRNG$RandomIO.readFully(NativePRNG.java:424)
at sun.security.provider.NativePRNG$RandomIO.ensureBufferValid(NativePRNG.java:525)
at sun.security.provider.NativePRNG$RandomIO.implNextBytes(NativePRNG.java:544)
at sun.security.provider.NativePRNG$RandomIO.access$400(NativePRNG.java:331)
at sun.security.provider.NativePRNG.engineNextBytes(NativePRNG.java:220)
at java.security.SecureRandom.nextBytes(SecureRandom.java:468)
at java.util.UUID.randomUUID(UUID.java:145)

BlockHound*.[jar|dylib] left in /tmp

After some playing with microbenchmarks for BlockHound (#35) I noticed the is a lot of jars and dylib files in my /tmp/

$ ls -1 /tmp/*BlockHound* | wc -l
170
$ ls -1 /tmp/*BlockHound* | head -n3
/tmp/BlockHound10045618520840685603.dylib
/tmp/BlockHound10356114630663133607.dylib
/tmp/BlockHound10396259701588337350.jar

Maybe they could be automatically cleaned up.

Blocking call during SSL handshake in WebFlux/ReactorNetty TcpServer

I enabled BlockHound on a spring boot 2.1.6, webflux, reactor netty server for which I want to run integration tests against. Unfortunately, I immediately ran into the blocking call below when connecting to it over SSL.

I honestly don't think there's anything that can be done to prevent that blocking call. (or is there?)

So, I need to configure a BlockHoundIntegration that allows this call. It seems like this would be a fairly frequently encountered use case, so it would be nice if the integration was automatically provided/discovered. Where should the integration be provided? BlockHound, reactor-netty? webflux? And which method would you recommend whitelisting?

2019-07-24 21:32:54.746 ERROR 96 --- [or-http-epoll-1] reactor.netty.tcp.TcpServer              : [id: 0xa2f9aafe, L:/127.0.0.1:46174 ! R:/127.0.0.1:34664] onUncaughtException(SimpleConnection{channel=[id: 0xa2f9aafe, L:/127.0.0.1:46174 ! R:/127.0.0.1:34664]})

java.lang.Error: Blocking call! java.io.FileInputStream#readBytes
	at reactor.blockhound.BlockHound$Builder.lambda$new$0(BlockHound.java:159)
	at reactor.blockhound.BlockHound$Builder.lambda$install$8(BlockHound.java:259)
	at reactor.blockhound.BlockHoundRuntime.checkBlocking(BlockHoundRuntime.java:43)
	at java.base/java.io.FileInputStream.readBytes(FileInputStream.java)
	at java.base/java.io.FileInputStream.read(FileInputStream.java:279)
	at java.base/java.io.FilterInputStream.read(FilterInputStream.java:133)
	at java.base/sun.security.provider.NativePRNG$RandomIO.readFully(NativePRNG.java:424)
	at java.base/sun.security.provider.NativePRNG$RandomIO.ensureBufferValid(NativePRNG.java:526)
	at java.base/sun.security.provider.NativePRNG$RandomIO.implNextBytes(NativePRNG.java:545)
	at java.base/sun.security.provider.NativePRNG.engineNextBytes(NativePRNG.java:220)
	at java.base/java.security.SecureRandom.nextBytes(SecureRandom.java:741)
	at java.base/sun.security.ssl.RandomCookie.<init>(RandomCookie.java:67)
	at java.base/sun.security.ssl.SessionId.<init>(SessionId.java:45)
	at java.base/sun.security.ssl.SSLSessionImpl.<init>(SSLSessionImpl.java:166)
	at java.base/sun.security.ssl.ServerHello$T12ServerHelloProducer.produce(ServerHello.java:281)
	at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
	at java.base/sun.security.ssl.ClientHello$T12ClientHelloConsumer.consume(ClientHello.java:1101)
	at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:851)
	at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:810)
	at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)
	at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1065)
	at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1052)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:999)
	at io.netty.handler.ssl.SslHandler.runAllDelegatedTasks(SslHandler.java:1502)
	at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1516)
	at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1400)
	at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1227)
	at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1274)
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:502)
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:441)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:278)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930)
	at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:796)
	at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:432)
	at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:333)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at java.base/java.lang.Thread.run(Thread.java:834)

Unable to whitelist java.io.RandomAccessFile#readBytes

Have all other tests passing with the exception of this one, which uses a WebTestClient.bindToServer()... usage.
All other tests using WebTestClient.bindToServer()... work correctly.

However, this test, the third test in a test flow, performs the validation of a JWT. But always fails due to:
eactor.blockhound.BlockingOperationError: Blocking call! java.io.RandomAccessFile#readBytes
at java.base/java.io.RandomAccessFile.readBytes(RandomAccessFile.java) and returns a 400 bad request.

I have tested the same endpoint with the server locally running and it works correctly, not in a test scenario.

Expected Behavior

I believe I should be able to add a 'allowBlockingCallsInside' to the integration class and this exception would not be generated.

As in the following:
/**

  • BlockHoundIntegration
  • Please see: https://medium.com/@domenicosibilio/blockhound-detect-blocking-calls-in-reactive-code-before-its-too-late-6472f8ad50c1
    */
    @log4j2
    public class AllowBlockingIntegration implements BlockHoundIntegration {
    @OverRide
    public void applyTo(Builder builder) {
    log.info("Applying {} Integrations ...", AllowBlockingIntegration.class.getSimpleName());
    builder
    .allowBlockingCallsInside(
    "org.apache.maven.surefire.booter.ForkingRunListener",
    "writeTestOutput")
    .allowBlockingCallsInside("java.io.FileOutputStream",
    "writeBytes")
    .allowBlockingCallsInside("java.io.RandomAccessFile",
    "readBytes");
    log.info("{} Builder: {}", AllowBlockingIntegration.class.getSimpleName(), builder);
    }
    }

And in Junit 5 Test:
static {
// Block hound Initialization ... Available for existence of JVM ...
BlockHound.install( new AllowBlockingIntegration() );
}

Actual Behavior

The above is established with the 'AllowBlockingIntegration()' class and the other allows are working with the exception of the last for .allowBlockingCallsInside("java.io.RandomAccessFile",
"readBytes");

Full Stack Trace:

2020-07-29T14:44:52,895 INFO [reactor-http-nio-4] i.b.b.n.d.s.m.h.MaxAuthenticationHandler: Validating Access Token Request from remote:[Optional[/127.0.0.1:55286]] ...
2020-07-29T14:44:52,931 ERROR [reactor-http-nio-4] i.b.b.n.d.s.m.e.GlobalErrorAttributes: Processing Exception for request from: /127.0.0.1:55286 for /maxauth/api/v1/validate
2020-07-29T14:44:52,932 ERROR [reactor-http-nio-4] ....GlobalErrorAttributes: Runtime Exception Blocking call! java.io.RandomAccessFile#readBytes
reactor.blockhound.BlockingOperationError: Blocking call! java.io.RandomAccessFile#readBytes
at java.base/java.io.RandomAccessFile.readBytes(RandomAccessFile.java)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ? ....filter.CorsFilter [DefaultWebFilterChain]
|_ checkpoint ? org.springframework.cloud.sleuth.instrument.web.TraceWebFilter [DefaultWebFilterChain]
|_ checkpoint ? org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ? HTTP GET "/maxauth/api/v1/validate" [ExceptionHandlingWebHandler]
Stack trace:
at java.base/java.io.RandomAccessFile.readBytes(RandomAccessFile.java)
at java.base/java.io.RandomAccessFile.read(RandomAccessFile.java:406)
at java.base/java.io.RandomAccessFile.readFully(RandomAccessFile.java:470)
at java.base/java.util.zip.ZipFile$Source.readFullyAt(ZipFile.java:1304)
at java.base/java.util.zip.ZipFile$ZipFileInputStream.initDataOffset(ZipFile.java:998)
at java.base/java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:1013)
at java.base/java.util.zip.ZipFile$ZipFileInflaterInputStream.fill(ZipFile.java:468)
at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:159)
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:133)
at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.base/java.io.InputStreamReader.read(InputStreamReader.java:185)
at java.base/java.io.BufferedReader.fill(BufferedReader.java:161)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:326)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:392)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.parseLine(ServiceLoader.java:1129)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.parse(ServiceLoader.java:1169)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(ServiceLoader.java:1205)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1220)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1264)
at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1299)
at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1384)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:132)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:558)
at com.okta.jwt.JwtVerifiers.loadService(JwtVerifiers.java:58)
at com.okta.jwt.JwtVerifiers.accessTokenVerifierBuilder(JwtVerifiers.java:51)
at ....okta.OktaAuthenticationServiceImpl.obtainTokenVerifier(OktaAuthenticationServiceImpl.java:194)
at ....okta.OktaAuthenticationServiceImpl.validateAccessToken(OktaAuthenticationServiceImpl.java:149)
at .... XXXAuthenticationHandler.validate(MaxAuthenticationHandler.java:169)
at org.springframework.web.reactive.function.server.support.HandlerFunctionAdapter.handle(HandlerFunctionAdapter.java:61)
at org.springframework.web.reactive.DispatcherHandler.invokeHandler(DispatcherHandler.java:161)
at org.springframework.web.reactive.DispatcherHandler.lambda$handle$1(DispatcherHandler.java:146)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:274)
at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:851)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onNext(FluxConcatArray.java:176)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onNext(FluxConcatArray.java:176)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onNext(FluxConcatArray.java:176)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onNext(FluxConcatArray.java:176)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onNext(FluxConcatArray.java:176)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2344)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.request(ScopePassingSpanSubscriber.java:76)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2152)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2026)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onSubscribe(ScopePassingSpanSubscriber.java:69)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.Mono.subscribe(Mono.java:4219)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:207)
at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:80)
at reactor.core.publisher.Mono.subscribe(Mono.java:4219)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:207)
at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:80)
at reactor.core.publisher.Mono.subscribe(Mono.java:4219)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:207)
at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:80)
at reactor.core.publisher.Mono.subscribe(Mono.java:4219)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:207)
at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:80)
at reactor.core.publisher.Mono.subscribe(Mono.java:4219)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:207)
at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:80)
at reactor.core.publisher.Mono.subscribe(Mono.java:4219)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:441)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:243)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxIterable$IterableSubscription.slowPath(FluxIterable.java:267)
at reactor.core.publisher.FluxIterable$IterableSubscription.request(FluxIterable.java:225)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.request(ScopePassingSpanSubscriber.java:76)
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:228)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onSubscribe(ScopePassingSpanSubscriber.java:69)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:161)
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:86)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at org.springframework.cloud.sleuth.instrument.web.TraceWebFilter$MonoWebFilterTrace.subscribe(TraceWebFilter.java:165)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.Mono.subscribe(Mono.java:4219)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172)
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.netty.http.server.HttpServerHandle.onStateChange(HttpServerHandle.java:64)
at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:514)
at reactor.netty.tcp.TcpServerBind$ChildObserver.onStateChange(TcpServerBind.java:267)
at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:465)
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:96)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:170)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
2020-07-29T14:44:52,952 DEBUG [reactor-http-nio-3] o.s.c.l.LogFormatUtils: [64b262a7] Response 400 BAD_REQUEST

Some class names obfuscated.

Steps to Reproduce

Could be difficult to reproduce, but attempt to use an Okta Library for JWT verification and that should lead you down the path.

It does not appear that you can allow the RandomAccessFile class methods, perhaps due to being native? Not sure.

            builder.allowBlockingCallsInside("java.io.RandomAccessFile",
                        "readBytes");

Possible Solution

Your Environment

Using:

SpringBoot 2.3.1 Base with WebFlex Starter
io.projectreactor.tools:blockhound:1.0.4.RELEASE
io.projectreactor.:reactor-test:3.3.6.RELEASE

  • Reactor version(s) used: 3.3.6

  • Other relevant libraries versions (eg. netty, ...): Yes, Netty being pulled in per Webflux Starter.

  • JVM version (javar -version):
    $ java --version
    openjdk 11.0.6 2020-01-14
    OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10)
    OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.6+10, mixed mode)

  • OS and version (eg uname -a):
    $ uname -a
    MINGW64_NT-10.0-18363 ******************** 3.0.7-338.x86_64 2019-11-21 23:07 UTC x86_64 Msys

Mockito.mock fails with BlockHound

Mockito.mock fails when blockhound-junit-platform is added to project dependencies.

Expected Behavior

Removing blockhound-junit-platform from dependencies makes the tests pass. I'd expect tests to pass with BlockHound.

Actual Behavior

[ERROR] testSomeScenario  Time elapsed: 0.001 s  <<< ERROR!
java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)
        at SomeServiceUTest.testSomeScenario(SomeServiceUTest.java:32)
Caused by: java.lang.IllegalStateException: Failed to load interface org.mockito.plugins.MockMaker implementation declared in sun.misc.CompoundEnumeration@b90c5a5
Caused by: org.mockito.exceptions.base.MockitoInitializationException: 

Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)

Java               : 1.8
JVM vendor name    : AdoptOpenJDK
JVM vendor version : 25.242-b08
JVM name           : OpenJDK 64-Bit Server VM
JVM version        : 1.8.0_242-b08
JVM info           : mixed mode
OS name            : Mac OS X
OS version         : 10.14.6

Caused by: java.lang.IllegalStateException: Error during attachment using: net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Compound@30c03473
Caused by: java.lang.reflect.InvocationTargetException
Caused by: java.lang.UnsatisfiedLinkError: Native Library /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/libattach.dylib already loaded in another classloader

Steps to Reproduce

@Test
public void testSomeScenario() {
    mock(Object.class);
}

Possible Solution

Looks like Byte Buddy dependency pulled transitively by mockito-core doesn't play nicely with the shaded copy of Byte Buddy included in BlockHound library.

+- org.mockito:mockito-core:jar:3.3.3:test
|  +- net.bytebuddy:byte-buddy:jar:1.10.14:test
|  +- net.bytebuddy:byte-buddy-agent:jar:1.10.14:test
|  \- org.objenesis:objenesis:jar:2.6:test

Your Environment

  • io.projectreactor.tools:blockhound-junit-platform:jar:1.0.4.RELEASE
  • org.mockito:mockito-core:jar:3.3.3 (via org.springframework.boot:spring-boot-starter-test:jar:2.3.4.RELEASE)
  • org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.3.4.RELEASE (via org.springframework.boot:spring-boot-starter-webflux:jar:2.3.4.RELEASE)
  • io.projectreactor:reactor-test:jar:3.3.10.RELEASE
  • 1.8.0_242-b08 OpenJDK 64-Bit Server VM
  • Mac OS X 10.14.6

Dynamic Thread Predicate doesn't work on thread that installs BlockHound

Expected Behavior

When I set all threads to be dynamic I expect the thread predicate to be called whenever a blocking call is found.

Actual Behavior

The STATE local variable in BlockHoundRuntime is set when it creates a test thread and has the default dynamic predicate defined, thus not allowing the invoking thread to use dynamic predicates.

Steps to Reproduce

public class CoreTestBlockHoundIntegration implements BlockHoundIntegration {
   public static final ThreadLocal<Boolean> checkBlocking = ThreadLocal.withInitial(() -> Boolean.FALSE);
   @Override
   public void applyTo(BlockHound.Builder builder) {
      builder.addDynamicThreadPredicate(t -> true);
      builder.nonBlockingThreadPredicate(threadPredicate -> threadPredicate.or(t -> {
         return checkBlocking.get() == Boolean.TRUE;
      }));
   }   
}
@Test
public void nonBlockingCase() throws TimeoutException {
   Thread.sleep(100);
   CoreTestBlockHoundIntegration.checkBlocking.set(Boolean.TRUE);
   try {
     // Should fail here but doesn't
     Thread.sleep(100);
   } finally {
      CoreTestBlockHoundIntegration.checkBlocking.set(Boolean.FALSE);      
   }
}

Here is the stack trace showing the BlockHoundRuntime.STATE variable being initialized at the incorrect time since the ClassLoader.loadClass method is instrumented it initializes the STATE. But since it still has the default dynamic thread predicate it always sets it to false.

"main@1" prio=5 tid=0x1 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
	  at reactor.blockhound.BlockHoundRuntime.lambda$static$0(BlockHoundRuntime.java:62)
	  at reactor.blockhound.BlockHoundRuntime$$Lambda$131.1556520190.get(Unknown Source:-1)
	  at java.lang.ThreadLocal$SuppliedThreadLocal.initialValue(ThreadLocal.java:305)
	  at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:195)
	  at java.lang.ThreadLocal.get(ThreadLocal.java:172)
	  at java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	  at reactor.blockhound.TestThread.<init>(TestThread.java:29)
	  at reactor.blockhound.BlockHound$Builder.testInstrumentation(BlockHound.java:415)
	  at reactor.blockhound.BlockHound$Builder.install(BlockHound.java:401)
	  at reactor.blockhound.BlockHound.install(BlockHound.java:94)

Possible Solution

The BlockHoundRuntime.STATE thread local should be reset after it has set the proper dynamic thread predicate.

This can be done at

BlockHoundRuntime.dynamicThreadPredicate = dynamicThreadPredicate;

For the time being I have to spawn a thread that just invokes BlockHound.install, which is quite ugly.

      Thread otherThread = new Thread(() -> BlockHound.install());
      otherThread.start();
      try {
         otherThread.join();
      } catch (InterruptedException e) {
         throw new RuntimeException(e);
      }

Your Environment

  • Reactor version(s) used: Blockhound 1.0.3.RELEASE
  • Other relevant libraries versions (eg. netty, ...):
  • JVM version (javar -version):
  • OS and version (eg uname -a):

3rd party threads

We should support checking threads originated from the 3rd party reactive libraries (RxJava, Cassandra, etc).

Some thoughts:

  • the easiest option would be to check their names, although it is not 100% reliable.
  • there might be something on the stacktrace to determine whenever the operation can be blocking or not

get NullPointerException when using BlockHound in springwebflux

get NullPointerException when I add BlockHound.install(); in spring webflux :

@SpringBootApplication
@EnableCaching
public class DemoApplication{

    public static void main(String[] args) {
        BlockHound.install();

        System.setProperty("reactor.netty.http.server.accessLogEnabled", "true");
        SpringApplication.run(DemoApplication.class, args);
    }
}

Exception:

java.lang.NullPointerException
	at reactor.BlockHoundRuntime.<clinit>(BlockHoundRuntime.java:31)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at reactor.BlockHound$Builder.install(BlockHound.java:227)
	at reactor.BlockHound.install(BlockHound.java:63)
	at com.huaweicloud.resourceprovider.openstack.DemoApplication.main(DemoApplication.java:16)
Exception in thread "main" java.lang.RuntimeException: java.lang.ExceptionInInitializerError
	at reactor.BlockHound$Builder.install(BlockHound.java:276)
	at reactor.BlockHound.install(BlockHound.java:63)
	at com.huaweicloud.resourceprovider.openstack.DemoApplication.main(DemoApplication.java:16)
Caused by: java.lang.ExceptionInInitializerError
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at reactor.BlockHound$Builder.install(BlockHound.java:227)
	... 2 more
Caused by: java.lang.RuntimeException: java.lang.NullPointerException
	at reactor.BlockHoundRuntime.<clinit>(BlockHoundRuntime.java:38)
	... 7 more
Caused by: java.lang.NullPointerException
	at reactor.BlockHoundRuntime.<clinit>(BlockHoundRuntime.java:31)
	... 7 more

Can you tell me where it is causing the error?

[Question] Need opinion on whether to allow a blocking call in spring-core

@bsideup I'd like to get your opinion on the blocking call encountered in the stacktrace below.

I'm trying to figure out:

  1. if it should be whitelisted,
  2. what should be whitelisted, and
  3. where it should be whitelisted.

My current thought is that

  1. yes, it should be whitelisted
  2. org.springframework.util.ConcurrentReferenceHashMap.doTask
  3. a blockhound integration provided by spring-core.

What are your thoughts?

java.lang.Error: Blocking call! jdk.internal.misc.Unsafe#park
	at reactor.blockhound.BlockHound$Builder.lambda$new$0(BlockHound.java:196)
	at reactor.blockhound.BlockHound$Builder.lambda$install$6(BlockHound.java:318)
	at reactor.blockhound.BlockHoundRuntime.checkBlocking(BlockHoundRuntime.java:46)
	at java.base/jdk.internal.misc.Unsafe.park(Unsafe.java)
	at java.base/java.util.concurrent.locks.LockSupport.park(LockSupport.java:194)
	at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:885)
	at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:917)
	at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1240)
	at java.base/java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:267)
	at org.springframework.util.ConcurrentReferenceHashMap$Segment.doTask(ConcurrentReferenceHashMap.java:524)
	at org.springframework.util.ConcurrentReferenceHashMap.doTask(ConcurrentReferenceHashMap.java:419)
	at org.springframework.util.ConcurrentReferenceHashMap.put(ConcurrentReferenceHashMap.java:282)
	at org.springframework.util.ConcurrentReferenceHashMap.put(ConcurrentReferenceHashMap.java:271)
	at org.springframework.core.ResolvableType.forType(ResolvableType.java:1420)
	at org.springframework.core.ResolvableType.forType(ResolvableType.java:1344)
	at org.springframework.web.reactive.function.BodyExtractors.toMono(BodyExtractors.java:80)
	at org.springframework.security.oauth2.core.web.reactive.function.OAuth2AccessTokenResponseBodyExtractor.extract(OAuth2AccessTokenResponseBodyExtractor.java:59)
	at org.springframework.security.oauth2.core.web.reactive.function.OAuth2AccessTokenResponseBodyExtractor.extract(OAuth2AccessTokenResponseBodyExtractor.java:48)
	at org.springframework.web.reactive.function.client.DefaultClientResponse.body(DefaultClientResponse.java:110)
	at org.springframework.security.oauth2.client.endpoint.WebClientReactiveClientCredentialsTokenResponseClient.lambda$null$0(WebClientReactiveClientCredentialsTokenResponseClient.java:85)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118)
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:203)
	at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:203)
	at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:242)
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2186)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribeInner(MonoFlatMapMany.java:143)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onSubscribe(MonoFlatMapMany.java:237)
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
	at reactor.core.publisher.Flux.subscribe(Flux.java:8143)
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:188)
	at reactor.core.publisher.FluxRetryPredicate$RetryPredicateSubscriber.onNext(FluxRetryPredicate.java:82)
	at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:156)
	at reactor.netty.http.client.HttpClientConnect$HttpObserver.onStateChange(HttpClientConnect.java:397)
	at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:494)
	at reactor.netty.resources.PooledConnectionProvider$DisposableAcquire.onStateChange(PooledConnectionProvider.java:526)
	at reactor.netty.resources.PooledConnectionProvider$PooledConnection.onStateChange(PooledConnectionProvider.java:435)
	at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:521)
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:89)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:326)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:313)
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:427)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:281)
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931)
	at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:792)
	at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:502)
	at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:407)
	at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1050)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:834)

Native library name on Windows incorrect

I believe the packaged native library name for Windows is incorrect. The call System.mapLibraryName("BlockHound") resolves to BlockHound.dll on Windows, while the library is packaged as libBlockHound.dll.

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:67)
Caused by: java.util.ServiceConfigurationError: org.junit.platform.launcher.TestExecutionListener: Provider reactor.blockhound.junit.platform.BlockHoundTestExecutionListener could not be instantiated
	at java.util.ServiceLoader.fail(ServiceLoader.java:232)
	at java.util.ServiceLoader.access$100(ServiceLoader.java:185)
	at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:384)
	at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
	at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
	at java.lang.Iterable.forEach(Iterable.java:74)
	at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:94)
	at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:67)
	at com.intellij.junit5.JUnit5IdeaTestRunner.createListeners(JUnit5IdeaTestRunner.java:42)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:45)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
	... 5 more
Caused by: java.lang.ExceptionInInitializerError
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.lang.Class.newInstance(Class.java:442)
	at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380)
	... 14 more
Caused by: java.lang.RuntimeException: java.lang.IllegalStateException: Failed to load the following lib from a classpath: BlockHound.dll
	at reactor.BlockHound$Builder.install(BlockHound.java:264)
	at reactor.BlockHound.install(BlockHound.java:64)
	at reactor.blockhound.junit.platform.BlockHoundTestExecutionListener.<clinit>(BlockHoundTestExecutionListener.java:12)
	... 20 more
Caused by: java.lang.IllegalStateException: Failed to load the following lib from a classpath: BlockHound.dll
	at reactor.BlockHound.extractNativeLibFile(BlockHound.java:298)
	at reactor.BlockHound.access$100(BlockHound.java:42)
	at reactor.BlockHound$Builder.install(BlockHound.java:227)
	... 22 more

I tested against latest Build-Snapshot from 22-Feb-2019 14:43 on Java 8. Thank you.

BlockHound should use specific Error sub-type

Would it make sense to throw a specific Error sub-type to make it easier for users to do something that fits for them.

For example something like public class BlockingOperationError extends Error

outputStream.write(byteArray) is not detected as blocking call

I am trying to use BlockHound in my spring boot application to detect the blocking scenario but it can't detect Logback ch.qos.logback.core.OutputStreamAppender outputStream.write(byteArray) as a blocker.

Expected Behavior

Since outputStream.write(byteArray) is blocking I/O operation, so BlockHound should detect this as a blocking call.

Actual Behavior

Can't detect ch.qos.logback.core.OutputStreamAppender outputStream.write(byteArray) as a blocker.

Steps to Reproduce

Any scratch spring boot project with net.logstash.logback:logstash-logback-encoder:6.4

Possible Solution

reactor.blockhound.integration.LoggingIntegration#applyTo allowing ch.qos.logback.classic.Logger#callAppenders as blocking call. But callAppenders eventually call ch.qos.logback.core.UnsynchronizedAppenderBase#append.

There are several implementation of ch.qos.logback.core.UnsynchronizedAppenderBase abstract class. Some are blocking and some are non-blocking. So, it would be good to remove the following code from reactor.blockhound.integration.LoggingIntegration#applyTo method.

try {
Class.forName("ch.qos.logback.classic.Logger");
builder.allowBlockingCallsInside("ch.qos.logback.classic.Logger", "callAppenders");
} catch (ClassNotFoundException e) {
}

https://github.com/qos-ch/logback/blob/a154cd1b564d436c90a26b8cb1a2e8ffff0a4a47/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java#L197-L205

Your Environment

  • Reactor version(s) used: 3.3.0.RELEASE
  • Other relevant libraries versions (eg. netty, ...): logstash-logback-encoder:6.4
  • JVM version (javar -version): openjdk version "11.0.6"
  • OS and version (eg uname -a): Ubuntu 18.04 LTS

[I think it's reproducible from any environment]

Getting Exceptions when stop application

Hello, i try to use BlockHound, what i do:

  1. add line BlockHound.install () to my SpringBootApplication class
  2. start application
  3. stop application

what i get:
image
which is remarkable, I don't see a line of code with a lock on it.

can you help me with that?

Not getting exception in blocking call

Hello,

I want to use blockhound for my scala application. To try out capabilities I have written following sample,

import reactor.blockhound.BlockHound

object Main extends App {
  val builder = BlockHound.builder()
  builder.install()
  builder.disallowBlockingCallsInside(
    "scala.Console$",
    "println"
  )
  builder.blockingMethodCallback(m => {
    new Exception(m.toString).printStackTrace()
  })
  builder.blockingMethodCallback(println)
  println("************************")
}

Expected Behaviour

I am dis allowing blocking call in println So I am expecting blockhound to throw exception.

Actual Behaviour

No exception is thrown. Program runs and prints ********

Environment

  • Reactor version(s) used: 1.0.2.RELEASE
  • JVM version (javar -version): openjdk version "11.0.2"
  • OS and version (eg uname -a): Darwin Kernel Version 19.2.0

Is there any sample scala project where I can look for usage of blockhound.

Note - Application runs from sbt console. But I am not getting intelliJ support while writing and running code. Might be my machine issue.
I have added Dependency in build.sbt "io.projectreactor.tools" % "blockhound" % "1.0.2.RELEASE"

Can't whitelist blocking lambda in Mono.fromRunnable

While enabling BlockHound for reactive work I've done in a spring-statemachine space there was a one test where I had to extract blocking sleep out from a lambda order to define it in a BlockHoundIntegration.

This was a change I had to make in my tests to extract Thread.sleep() out from it:
https://github.com/spring-projects/spring-statemachine/blob/9e0bdae46fd80b2242c61149cf3d08987a9feedf/spring-statemachine-core/src/test/java/org/springframework/statemachine/state/ObjectStateTests.java#L155-L183

Then I defined sleep as:
https://github.com/spring-projects/spring-statemachine/blob/9e0bdae46fd80b2242c61149cf3d08987a9feedf/spring-statemachine-core/src/test/java/org/springframework/statemachine/StateMachineBlockHoundIntegration.java#L31

Previously having

.allowBlockingCallsInside("org.springframework.statemachine.state.ObjectStateTests$TestBlockingAction", "apply")

just didn't work.

BlockHound does not detect Thread.sleep() in Spring/Kotlin/WebFlux setup

Expected Behavior

BlockHound should detect that a blocking call was made in controller method

Actual Behavior

Thread.sleep() works as normal blocking the thread.

Steps to Reproduce

import kotlinx.coroutines.debug.CoroutinesBlockHoundIntegration
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import reactor.blockhound.BlockHound

@SpringBootApplication
class SampleApplication

@RestController
@RequestMapping("/samples")
class SampleController {

	@GetMapping
	fun sampleGet(): String {
		Thread.sleep(4000)
		return "hello there"
	}
}

fun main(args: Array<String>) {
	BlockHound.builder()
		.with(CoroutinesBlockHoundIntegration())
		.install()

	runApplication<SampleApplication>(*args)
}

Your Environment

  • build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
	id("org.springframework.boot") version "2.4.3"
	id("io.spring.dependency-management") version "1.0.11.RELEASE"
	kotlin("jvm") version "1.4.30"
	kotlin("plugin.spring") version "1.4.30"
}

group = "sample"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
	mavenCentral()
}

dependencies {

	implementation("org.springframework.boot:spring-boot-starter-webflux")
	implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")

	// Kotlin related
	implementation("org.jetbrains.kotlin:kotlin-reflect")
	implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
	implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
	implementation("com.fasterxml.jackson.module:jackson-module-kotlin")

	implementation("io.projectreactor.tools:blockhound:1.0.4.RELEASE")
	implementation("org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.4.0-M1")

	testImplementation("org.springframework.boot:spring-boot-starter-test")
	testImplementation("io.projectreactor:reactor-test")
}

tasks.withType<KotlinCompile> {
	kotlinOptions {
		freeCompilerArgs = listOf("-Xjsr305=strict")
		jvmTarget = "11"
	}
}

tasks.withType<Test> {
	useJUnitPlatform()
}
  • JVM version (java -version):
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
  • OS and version (eg uname -a):
Darwin macbook.local 19.6.0 Darwin Kernel Version 19.6.0: Thu Jun 18 20:49:00 PDT 2020; root:xnu-6153.141.1~1/RELEASE_X86_64 x86_64

BlockHound does not detect that any blocking call if i enable spring security @EnableWebFluxSecurity

Expected Behavior

BlockHound should detect that any blocking call if i enable spring security @EnableWebFluxSecurity

Actual Behavior

BlockHound does not detect that any blocking call if i enable spring security @EnableWebFluxSecurity

Steps to Reproduce

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>
@EnableWebFluxSecurity
public class SecurityConfig {
	@Bean
	public MapReactiveUserDetailsService userDetailsService() {
		UserDetails user = User.withUsername("admin").password(passwordEncoder().encode("password")).roles("ADMIN")
				.build();
		return new MapReactiveUserDetailsService(user);
	}

	@Bean
	public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
		http.csrf().disable().authorizeExchange().pathMatchers("/**").permitAll().and().httpBasic();
		return http.build();
	}

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
}

Your Environment

  • Reactor version(s) used: reactor-core/3.4.3
  • Other relevant libraries versions (eg. netty, ...): r2dbc-h2/0.8.4, hazelcast, hazelcast-spring, spring-boot/2.4.3
  • JVM version (java -version): 11.0.10
  • OS and version (eg uname -a): Windows 10

Provide API/documentation on how to allow/disallow blocking calls inside static initializer

See also #174, where a similar API/documentation should be provided for constructors.

Quoting from the above:

There is no guidance I could find on how to allow/disallow blocking in a constructor or static initializer. There is one test that shows how to do it for a static initializer but it would be nicer if it was easier to find. One option could be a dedicated method, e.g. allowBlockingCallsInsideConstructor(String classname), or otherwise provide guidance in the Javadoc on allowBlockingCallsInside and a mention on the Customizations page.

@rstoyanchev you suggested that additional methods would maybe increase the API too much, and suggested enums or varargs. How about a couple constants? Something like:

//in Blockhound.Builder class, or directly at root Blockhound.java
public static final String STATIC_INITIALIZER = "<clinit>";

//in user code
BlockHound.install(b -> b.allowBlockingCallsInside(ClassWithStaticInit.class.getName(), BlockHound.Builder.STATIC_INITIALIZER));

Not working under OpenJ9

Environment:
openjdk 11.0.1 2018-10-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.1+13)
Eclipse OpenJ9 VM AdoptOpenJDK (build openj9-0.11.0, JRE 11 Mac OS X amd64-64-Bit Compressed References 20181115_16 (JIT enabled, AOT enabled)

OpenJ9 - 090ff9dcd
OMR - ea548a66
JCL - d4455071ce based on jdk-11.0.1+13)

Stacktrace:

org.gradle.api.internal.tasks.testing.TestSuiteExecutionException: Could not complete execution for Gradle Test Executor 10.
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:63)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy4.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:175)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:157)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
    at java.base/java.lang.Thread.run(Thread.java:825)
Caused by: java.util.ServiceConfigurationError: org.junit.platform.launcher.TestExecutionListener: Provider reactor.blockhound.junit.platform.BlockHoundTestExecutionListener could not be instantiated
    at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:581)
    at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:803)
    at java.base/java.util.ServiceLoader$ProviderImpl.get(ServiceLoader.java:721)
    at java.base/java.util.ServiceLoader$3.next(ServiceLoader.java:1394)
    at java.base/java.lang.Iterable.forEach(Iterable.java:74)
    at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:94)
    at org.junit.platform.launcher.core.LauncherFactory.create(LauncherFactory.java:67)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:100)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:82)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:78)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    ... 25 more
Caused by: java.lang.ExceptionInInitializerError
    at java.base/java.lang.J9VMInternals.ensureError(J9VMInternals.java:191)
    at java.base/java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:180)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:779)
    ... 34 more
Caused by: java.lang.RuntimeException: java.lang.instrument.UnmodifiableClassException
    at reactor.BlockHound$Builder.install(BlockHound.java:264)
    at reactor.BlockHound.install(BlockHound.java:64)
    at reactor.blockhound.junit.platform.BlockHoundTestExecutionListener.<clinit>(BlockHoundTestExecutionListener.java:12)
    ... 39 more
Caused by: java.lang.instrument.UnmodifiableClassException
    at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
    at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167)
    at reactor.BlockHound$Builder.instrument(BlockHound.java:273)
    at reactor.BlockHound$Builder.install(BlockHound.java:261)
    ... 41 more

OpenJDK 13 requires -XX:+AllowRedefinitionToAddDeleteMethods flag

OpenJDK 12.0.1 with even Kotlin 1.3.40-eap-67 works fine. However, using OpenJDK 13 build 23 I get the following exception:

Exception in thread "main" java.lang.RuntimeException: java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method
        at reactor.blockhound.BlockHound$Builder.install(BlockHound.java:264)
        at reactor.blockhound.BlockHound.install(BlockHound.java:64)
        at de.hska.kunde.ApplicationKt.main(Application.kt:51)
Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method
        at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
        at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167)
        at reactor.blockhound.BlockHound$Builder.instrument(BlockHound.java:273)
        at reactor.blockhound.BlockHound$Builder.install(BlockHound.java:261)
        ... 2 more

Ability to ignore blocking calls in a static initializer

Not sure if it is possible, but it would be useful to have the option to ignore blocking calls occurring in the initialization of static fields.

Motivation

In this specific example, Build will use an InputStream, but the resulting blocking call to readBytes is not detrimental to the event loop threads in the long run, since it is only called once when the string is initialized.

static {
		PREFIX = String.format(Locale.ROOT,
				"%s%s",
				Version.CURRENT.toString(),
				Build.CURRENT.isSnapshot() ? "-SNAPSHOT" : "");
	}

Application does not start with BlockHound and ReactorDebugAgent installed on java 8

BlockHound and ReactorDebugAgent cannot work together on java 8.
Application fails with error

java.util.ServiceConfigurationError: com.sun.tools.attach.spi.AttachProvider: Provider sun.tools.attach.WindowsAttachProvider could not be instantiated
java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalStateException: Error during attachment using: reactor.tools.shaded.net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Compound@53aac487
	at reactor.tools.shaded.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:400)
	at reactor.tools.shaded.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:374)
	at reactor.tools.shaded.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:342)
	at reactor.tools.shaded.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:328)
	at reactor.tools.agent.ReactorDebugAgent.init(ReactorDebugAgent.java:41)
	at com.example.demo.ReactorDebugApplication.<clinit>(ReactorDebugApplication.java:27)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at reactor.tools.shaded.net.bytebuddy.agent.Attacher.install(Attacher.java:99)
	at reactor.tools.shaded.net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:395)
	... 5 more
Caused by: com.sun.tools.attach.AttachNotSupportedException: no providers installed
	at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:203)
	... 11 more
Exception in thread "main" 

If I try to start application using java 11 or just disable BlockHound or ReactorDebugAgent (in the code and spring-boot integration) everything works fine.

Expected Behavior

application starts

Actual Behavior

application start fails

Steps to Reproduce

try to start application on java 8
https://github.com/robotmrv/reactor-debug-error

Possible Solution

Your Environment

  • Reactor version(s) used:
    io.projectreactor:reactor-core:3.3.0.RELEASE
    io.projectreactor:reactor-tools:3.3.0.RELEASE
    io.projectreactor.tools:blockhound:1.0.1.RELEASE
  • Other relevant libraries versions (eg. netty, ...):
  • JVM version (javar -version):
    java version "1.8.0_231"
    Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
    Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
  • OS and version (eg uname -a):
    Win 10

When Blockhound is used with EmbeddedKafka for unit test, kafka wont terminate

When Blockhound is used with EmbeddedKafka for unit test, Kafka won't terminate after the test is completed. If Blockhound is disabled, no problem in running tests.

Expected Behavior

After tests are completed, embedded Kafka should be terminated.

Actual Behavior

After tests are completed, embedded Kafka is not terminated. So other tests are not running and the system is waiting for Kafka to stop.

Steps to Reproduce

@SpringBootTest(classes = {KafkaConfiguration.class})
@EmbeddedKafka(partitions = 1, brokerProperties = {TestConstants.SERVER, TestConstants.PORT})
@DirtiesContext
@Slf4j
class OrderUpdateTest {

  @BeforeEach
  public void init() {
    BlockHound.install();
    log.info("Installed blockhound");
  }

  @Test
  public void testProducer()
    throws Exception {
     log.info("test");
  }

  @AfterEach
  public void after() {
    log.info("finished test");
  }
}

Your Environment

  • OS: macOS Big Sur
  • Java:JDK11
  • Spring Boot 2.4.2
  • Blockhound 1.0.4.RELEASE
  • Spring Kafka 2.5.6.RELEASE

JVM fatal error when in debug mode (jdk1.8.0_60), works with jdk1.8.0_211

When running a simple JUnit test in debug mode with a breakpoint enabled, the following fatal error occurs with JDK 8 (build 1.8.0_60-b27):

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x000000010d046914, pid=33734, tid=16903
#
# JRE version: Java(TM) SE Runtime Environment (8.0_60-b27) (build 1.8.0_60-b27)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.60-b23 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# V  [libjvm.dylib+0x446914]  Method::checked_resolve_jmethod_id(_jmethodID*)+0xe
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/jgrandja/workspace/issues/oauth2-client-nonblock/ui-app/hs_err_pid33734.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#
Disconnected from the target VM, address: '127.0.0.1:61502', transport: 'socket'

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

If I disable breakpoints, the test executes without error.

This error only happens in debug mode with at least one breakpoint enabled.

Config customization not respected

Hi,

My intent is to use BlockHound during unit tests and I wanted to give some exceptions. If I understand correctly, with the provided BlockHoundIntegration class, BlockHound should not trigger for the provided configurations.

Expected Behavior

Should not throw BlockingOperationError.

Actual Behavior

It throws BlockingOperationError

Steps to Reproduce

I've provided a demo application: gradlew test
demo.zip

Your Environment

  • JVM version (java -version): Oracle JDK 11.0.6
  • OS and version (eg uname -a): Windows 10

jvm crash during maven test run

Hi,

First of all thanks for the fantastic work, really appreciated.

I have a weird problem (jvm crash) when using BlockHound.

I am trying to use it on my integration test of an app. Indeed the app is somewhat complicated and I spin up some test containers
(https://www.testcontainers.org/) for kafka, db, elastic and use wiremock (http://wiremock.org/) for http dependency mocking.

When I run from my eclipse ide, the tests are fine. But running them via maven build makes jvm crash (and make tests fail)

I tried to nail down the issue and it seems to be a problem with blockhound coupling with wiremock (akthough not completely sure)

I implemented a minimal / simple reproducer project (https://github.com/simpleusr/ProblemDemoApp)

For all maven builds jvm crashes consistently as below but the place of crash seems to change randomly:

A fatal error has been detected by the Java Runtime Environment:

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000000004000, pid=49856, tid=19168

JRE version: Java(TM) SE Runtime Environment (8.0_25-b18) (build 1.8.0_25-b18)
Java VM: Java HotSpot(TM) 64-Bit Server VM (25.25-b02 mixed mode windows-amd64 compressed oops)
Problematic frame:
C 0x0000000000004000

Failed to write core dump. Minidumps are not enabled by default on client versions of Windows

If you would like to submit a bug report, please visit:
http://bugreport.sun.com/bugreport/crash.jsp

--------------- T H R E A D ---------------

Current thread (0x0000000000f0d800): JavaThread "main" [_thread_in_Java, id=19168, stack(0x00000000028d0000,0x00000000029d0000)]

siginfo: ExceptionCode=0xc0000005, ExceptionInformation=0x0000000000000008 0x0000000000004000

Registers:
RAX=0x00000006c2141be8, RBX=0x000000001bdee2a0, RCX=0x0000000002ad3180, RDX=0x00000006c2141be8
RSP=0x00000000029cc710, RBP=0xe5585fd151001191, RSI=0x00000007c00c1690, RDI=0x0000000020ead828
R8 =0x00000006c1e03ff0, R9 =0x0000000000000000, R10=0x00000006c2141be8, R11=0x0000000002c04a80
R12=0x0000000000000000, R13=0x00000000029cc700, R14=0x00000000029cc7a8, R15=0x0000000000f0d800
RIP=0x0000000000004000, EFLAGS=0x0000000000010246

Top of Stack: (sp=0x00000000029cc710)
0x00000000029cc710: 0000000000000000 0000000000f0e3f0
0x00000000029cc720: 00000000029cc790 00000000029d77b0
0x00000000029cc730: 0000000000000000 00000000029d77b0
0x00000000029cc740: 00000006c2141be8 00000006c1e03fd0
0x00000000029cc750: 00000000029cc750 00000000249011e6
0x00000000029cc760: 00000000029cc7a8 0000000024901268
0x00000000029cc770: 0000000000000000 00000000249011f8
0x00000000029cc780: 00000000029cc740 00000000029cc7b0
0x00000000029cc790: 00000000029cc7b0 0000000002f230c4
0x00000000029cc7a0: 00000006c2141be8 00000006c21346a8
0x00000000029cc7b0: 0000000000000000 0000000000000000
0x00000000029cc7c0: 0000000000000000 0000000002af6a99
0x00000000029cc7d0: 0000000000000000 0000000000000000
0x00000000029cc7e0: 00000000029cc858 00000000029d7958
0x00000000029cc7f0: 0000000000000000 00000000029d7958
0x00000000029cc800: 00000006c21346a8 00000006c1e19050

Instructions: (pc=0x0000000000004000)
0x0000000000003fe0:
[error occurred during error reporting (printing registers, top of stack, instructions near pc), id 0xc0000005]

Register to memory mapping:

RAX=0x00000006c2141be8 is an oop
org.springframework.util.MultiValueMapAdapter$$Lambda$79/105579928

  • klass: 'org/springframework/util/MultiValueMapAdapter$$Lambda$79'
    RBX={method} {0x000000001bdee2a8} 'identity' '(Ljava/lang/Object;)Ljava/lang/Object;' in 'sun/invoke/util/ValueConversions'
    RCX=0x0000000002ad3180 is at begin+12 in a stub
    MethodHandle::interpreter_entry::_linkToStatic [0x0000000002ad3174, 0x0000000002ad3198[ (36 bytes)
    RDX=0x00000006c2141be8 is an oop
    org.springframework.util.MultiValueMapAdapter$$Lambda$79/105579928
  • klass: 'org/springframework/util/MultiValueMapAdapter$$Lambda$79'

I am sure that this is related with blockhound because if I remove it (which I do not want for my test) crash does not happen.

The only diference between eclipse run and maven run seems to be the runner initiating the test run but they all delegate to SpringJUnit4ClassRunner eventually

at com.mycompany.problemdemo.ProblemDemoAppIntegrationTest.<clinit>(ProblemDemoAppIntegrationTest.java:36)
at sun.misc.Unsafe.ensureClassInitialized(Native Method)
at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:43)
at sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:142)
at java.lang.reflect.Field.acquireFieldAccessor(Field.java:1082)
at java.lang.reflect.Field.getFieldAccessor(Field.java:1063)
at java.lang.reflect.Field.get(Field.java:387)
at org.junit.runners.model.FrameworkField.get(FrameworkField.java:93)
at org.junit.runners.model.TestClass.collectAnnotatedFieldValues(TestClass.java:249)
at org.junit.runners.ParentRunner.classRules(ParentRunner.java:280)
at org.junit.runners.ParentRunner.withClassRules(ParentRunner.java:268)
at org.junit.runners.ParentRunner.classBlock(ParentRunner.java:217)
at org.junit.runners.ParentRunner.run(ParentRunner.java:412)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)

Any help would be appreciated

Regards

Be able to whitelist methods via annotation

It would be cool (and less fragile imho) if we could use an annotation to whitelist a method. The annotation itself should be "provided" by the user of blockhound (just like you can also suppress warning for animal sniffer with an annotation). This way even if a user renames a method etc it will not break the blockhound whitelist config.

NoClassDefFoundError: Failed resolution of: Ljava/lang/management/ManagementFactory on Android

I'm getting an exception with the following setup:

debugImplementation "io.projectreactor.tools:blockhound:1.0.0.M1"
if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            BlockHound.builder()
                .nonBlockingThreadPredicate { current -> current.or { it === Looper.getMainLooper().thread } }
                .install()
        }

Just a quick search gives a similar issue for Mockito: mockito/mockito#841
Can this library be used on Android in theory?

[Question] Is this the right way to customize blockhound-junit-platform?

Not really an issue, but I couldn't find a gitter channel for BlockHound where I would've asked this question otherwise :)

I'm playing around with BlockHound JUnit Platform for a little demo based on Project Reactor (https://github.com/dsibilio/blockhound-demo).

While fiddling with it, I noticed that the ch.qos.logback.classic.Logger#buildLoggingEventAndAppend got flagged downstack due to some blocking IO.

Of course I wanted to allow this method but I couldn't find a way to customize BlockHound before initialization since it gets done for me by the BlockHoundTestExecutionListener.java, so I had to:

So, as per title, is this the right way to allow/disallow custom methods when wanting to use blockhound-junit-platform? Or is there something obvious that I might've missed?

Thanks in advance :)

java.lang.IllegalStateException: Cannot resolve type description for org.slf4j.event.LoggingEvent

When I try to use BlockHound library in my Spring Boot application I get this exception when calling:

BlockHound.install();

Expected Behavior

BlockHound should successfully install.

Actual Behavior

[Byte Buddy] ERROR ch.qos.logback.classic.Logger [jdk.internal.loader.ClassLoaders$AppClassLoader@14514713, unnamed module @3b220bcb, loaded=true]
java.lang.IllegalStateException: Cannot resolve type description for org.slf4j.event.LoggingEvent
	at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$Resolution$Illegal.resolve(TypePool.java:159)
	at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$Default$LazyTypeDescription$TokenizedGenericType.toErasure(TypePool.java:6241)
	at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$Default$LazyTypeDescription$LazyTypeList.get(TypePool.java:6049)
	at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$Default$LazyTypeDescription$LazyTypeList.get(TypePool.java:6022)
	at java.base/java.util.AbstractList$Itr.next(AbstractList.java:371)

Steps to Reproduce

public class SampleReactor {

	public static void main(String[] args) {
		BlockHound.install();
}
}

Your Environment

Windows 10 Pro
JDK 11.0.2
Reactor 3.3.0
BlockHound 1.0.1
Spring Boot 2.2.1

Blocking call detected even when subscribed to Schedulers.boundedElastic()

Overview

We are planning to migrate our blocking Spring boot micro-service to a non-blocking IO Spring Webflux. During testing of our demo service, we used a blocking client(Jedis) to retrieve data from Redis but it was subscribed to Schedulers.elastic(), but still blockhound detected it as a blocking call

Expected Behavior

Because it was a normal thread pool(elastic), hence the blocking service shouldn't have been recognized as a blocking call.

Actual Behavior

Block hound detecting it as a blocking call. Stack trace:

2020-12-08 15:07:44,140 INFO  [main] o.s.b.w.e.n.NettyWebServer:109:[, ] - Netty started on port(s): 8080
2020-12-08 15:07:44,156 INFO  [main] c.m.d.DdReactiveApplication:61:[, ] - Started DdReactiveApplication in 5.037 seconds (JVM running for 5.735)
2020-12-08 15:07:50,809 ERROR [reactor-http-epoll-3] o.s.b.a.w.r.e.AbstractErrorWebExceptionHandler:122:[, ] - [aa0d19ef-1]  500 Server Error for HTTP GET "/getPolicyObj?key=a"
reactor.blockhound.BlockingOperationError: Blocking call! java.net.SocketOutputStream#socketWrite0
	at java.net.SocketOutputStream.socketWrite0(SocketOutputStream.java)
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	|_ checkpoint โ‡ข HTTP GET "/getPolicyObj?key=a" [ExceptionHandlingWebHandler]
Stack trace:
		at java.net.SocketOutputStream.socketWrite0(SocketOutputStream.java)
		at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
		at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
		at redis.clients.jedis.util.RedisOutputStream.flushBuffer(RedisOutputStream.java:52)
		at redis.clients.jedis.util.RedisOutputStream.flush(RedisOutputStream.java:133)
		at redis.clients.jedis.Connection.flush(Connection.java:265)
		at redis.clients.jedis.Connection.getBinaryBulkReply(Connection.java:214)
		at redis.clients.jedis.Connection.getBulkReply(Connection.java:205)
		at redis.clients.jedis.Jedis.get(Jedis.java:185)
		at redis.clients.jedis.JedisCluster$3.execute(JedisCluster.java:198)
		at redis.clients.jedis.JedisCluster$3.execute(JedisCluster.java:195)
		at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:106)
		at redis.clients.jedis.JedisClusterCommand.run(JedisClusterCommand.java:25)
		at redis.clients.jedis.JedisCluster.get(JedisCluster.java:200)
		at com.mmt.ddreactive.CacheUtil.get(CacheUtil.java:60)
		at com.mmt.ddreactive.service.DDService.getPolicyObjFromCacheFromJedis(DDService.java:123)
		at com.mmt.ddreactive.controller.DDController.getPolicyObj(DDController.java:88)
		at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
		at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
		at java.lang.reflect.Method.invoke(Method.java:498)
		at org.springframework.web.reactive.result.method.InvocableHandlerMethod.lambda$invoke$0(InvocableHandlerMethod.java:146)
		at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125)
		at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1784)
		at reactor.core.publisher.MonoZip$ZipCoordinator.signal(MonoZip.java:251)
		at reactor.core.publisher.MonoZip$ZipInner.onNext(MonoZip.java:336)
		at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180)
		at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:99)
		at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:73)
		at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2346)
		at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2154)
		at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2028)
		at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:191)
		at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53)
		at reactor.core.publisher.Mono.subscribe(Mono.java:3972)
		at reactor.core.publisher.MonoZip.subscribe(MonoZip.java:128)
		at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:154)
		at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
		at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
		at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
		at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:73)
		at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82)
		at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:281)
		at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:860)
		at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127)
		at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180)
		at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2346)
		at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.request(MonoPeekTerminal.java:139)
		at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:169)
		at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2154)
		at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2028)
		at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:96)
		at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onSubscribe(MonoPeekTerminal.java:152)
		at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
		at reactor.core.publisher.Mono.subscribe(Mono.java:3987)
		at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:448)
		at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:218)
		at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:164)
		at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:86)
		at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
		at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
		at reactor.core.publisher.Mono.subscribe(Mono.java:3987)
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:173)
		at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56)
		at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
		at reactor.netty.http.server.HttpServer$HttpServerHandle.onStateChange(HttpServer.java:611)
		at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:612)
		at reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:453)
		at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:510)
		at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
		at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:185)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
		at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
		at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
		at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
		at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
		at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
		at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
		at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795)
		at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480)
		at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378)
		at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
		at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
		at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
		at java.lang.Thread.run(Thread.java:748)

Steps to Reproduce

Calling this backend service function, here cacheUtil.get() is a blocking call to jedis.get(), but as it is subscribed to boundedElastic, it shouldn't be a blocking call.

public Mono<String> getPolicyObjFromCacheFromJedis(String key) {
    return Mono.just(cacheUtil.get(key)).subscribeOn(Schedulers.boundedElastic()).log();
  }

Possible Solution

NA

Your Environment

  • Reactor version(s) used:
    3.4.0
  • Other relevant libraries versions (eg. netty, ...):
    Netty version: 4.1.54.Final
  • JVM version (javar -version):
    Oracle JDK
    java version "1.8.0_231"
    Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
    Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
  • OS and version (eg uname -a):
    Linux mmt-ubt-8341 5.4.0-53-generic #59~18.04.1-Ubuntu SMP Wed Oct 21 12:14:56 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
  • Jedis version: 3.3.0
  • Blockhound version : 1.0.4.RELEASE

Blockhound 1.0.2 doesn't work with OpenJDK 14

I'm getting tons of IllegalArgumentExceptions with message Unsupported class file major version 58 as soon as I use BlockHound.install() in the beginning of main(). An extract of a few exceptions is attached at the end. Using OpenJDK 14 without BlockHound.install() works fine for my Kotlin-based Spring app which is compiled to JVM target 13 (being the latest supported target of the Kotlin compiler).

Expected Behavior

It should support the latest OpenJDK release.

Actual Behavior

Tons of exceptions.

Steps to Reproduce

Download OpenJDK 14 https://jdk.java.net/14 and use it instead of e.g. OpenJDK 11.

Possible Solution

Your Environment

OpenJDK 14, Windows 10 Enterprise

  • Reactor version(s) used: Dysprosium-SR5
  • Other relevant libraries versions (eg. netty, ...):
  • JVM version (javar -version): openjdk 14 2020-03-17
  • OS and version (eg uname -a): Windows 10.0.17134

Extract of the exceptions:

...
[Byte Buddy] ERROR java.net.SocketImpl [null, module java.base, loaded=false]
java.lang.IllegalArgumentException: Unsupported class file major version 58
        at reactor.blockhound.shaded.net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:195)
        at reactor.blockhound.shaded.net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:176)
        at reactor.blockhound.shaded.net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:162)
        at reactor.blockhound.shaded.net.bytebuddy.utility.OpenedClassReader.of(OpenedClassReader.java:82)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$Default.parse(TypePool.java:681)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$Default.doDescribe(TypePool.java:667)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$AbstractBase.describe(TypePool.java:408)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$AbstractBase$Hierarchical.describe(TypePool.java:484)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$DescriptionStrategy$Default$3.apply(AgentBuilder.java:3582)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.resolve(AgentBuilder.java:10524)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doTransform(AgentBuilder.java:10494)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10457)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.access$1500(AgentBuilder.java:10223)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:10907)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:10845)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10413)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$ByteBuddy$ModuleSupport.transform(Unknown Source)
        at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
        at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
        at java.base/sun.nio.ch.ServerSocketAdaptor.<init>(ServerSocketAdaptor.java:74)
        at java.base/sun.nio.ch.ServerSocketAdaptor.lambda$create$0(ServerSocketAdaptor.java:65)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
        at java.base/sun.nio.ch.ServerSocketAdaptor.create(ServerSocketAdaptor.java:67)
        at java.base/sun.nio.ch.ServerSocketChannelImpl.socket(ServerSocketChannelImpl.java:128)
        at java.base/sun.nio.ch.PipeImpl$Initializer$LoopbackConnector.run(PipeImpl.java:121)
        at java.base/sun.nio.ch.PipeImpl$Initializer.run(PipeImpl.java:76)
        at java.base/sun.nio.ch.PipeImpl$Initializer.run(PipeImpl.java:61)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
        at java.base/sun.nio.ch.PipeImpl.<init>(PipeImpl.java:171)
        at java.base/sun.nio.ch.SelectorProviderImpl.openPipe(SelectorProviderImpl.java:50)
        at java.base/java.nio.channels.Pipe.open(Pipe.java:155)
        at java.base/sun.nio.ch.WindowsSelectorImpl.<init>(WindowsSelectorImpl.java:142)
        at java.base/sun.nio.ch.WindowsSelectorProvider.openSelector(WindowsSelectorProvider.java:44)
        at java.base/java.nio.channels.Selector.open(Selector.java:295)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:160)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:214)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:227)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:231)
        at org.apache.kafka.clients.admin.KafkaAdminClient.createInternal(KafkaAdminClient.java:427)
        at org.apache.kafka.clients.admin.Admin.create(Admin.java:69)
        at org.apache.kafka.clients.admin.AdminClient.create(AdminClient.java:49)
        at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.createAdminClient(KafkaTopicProvisioner.java:239)
        at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.doProvisionConsumerDestination(KafkaTopicProvisioner.java:209)
        at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.provisionConsumerDestination(KafkaTopicProvisioner.java:181)
        at org.springframework.cloud.stream.binder.kafka.streams.KafkaStreamsBinderUtils.prepareConsumerBinding(KafkaStreamsBinderUtils.java:84)
        at org.springframework.cloud.stream.binder.kafka.streams.KStreamBinder.doBindConsumer(KStreamBinder.java:102)
        at org.springframework.cloud.stream.binder.kafka.streams.KStreamBinder.doBindConsumer(KStreamBinder.java:52)
        at org.springframework.cloud.stream.binder.AbstractBinder.bindConsumer(AbstractBinder.java:143)
        at org.springframework.cloud.stream.binding.BindingService.doBindConsumer(BindingService.java:169)
        at org.springframework.cloud.stream.binding.BindingService.bindConsumer(BindingService.java:115)
        at org.springframework.cloud.stream.binding.AbstractBindableProxyFactory.createAndBindInputs(AbstractBindableProxyFactory.java:112)
        at org.springframework.cloud.stream.binding.InputBindingLifecycle.doStartWithBindable(InputBindingLifecycle.java:58)
        at java.base/java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:647)
        at org.springframework.cloud.stream.binding.AbstractBindingLifecycle.start(AbstractBindingLifecycle.java:57)
        at org.springframework.cloud.stream.binding.InputBindingLifecycle.start(InputBindingLifecycle.java:34)
        at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182)
        at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53)
        at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360)
        at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158)
        at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122)
        at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:894)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
        at com.acme.receiver.ApplicationKt.main(Application.kt:88)
[Byte Buddy] ERROR java.net.SocketOptions [null, module java.base, loaded=false]
java.lang.IllegalArgumentException: Unsupported class file major version 58
        at reactor.blockhound.shaded.net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:195)
        at reactor.blockhound.shaded.net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:176)
        at reactor.blockhound.shaded.net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:162)
        at reactor.blockhound.shaded.net.bytebuddy.utility.OpenedClassReader.of(OpenedClassReader.java:82)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$Default.parse(TypePool.java:681)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$Default.doDescribe(TypePool.java:667)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$AbstractBase.describe(TypePool.java:408)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$AbstractBase$Hierarchical.describe(TypePool.java:484)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$DescriptionStrategy$Default$3.apply(AgentBuilder.java:3582)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.resolve(AgentBuilder.java:10524)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doTransform(AgentBuilder.java:10494)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10457)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.access$1500(AgentBuilder.java:10223)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:10907)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:10845)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10413)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$ByteBuddy$ModuleSupport.transform(Unknown Source)
        at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
        at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
        at java.base/sun.nio.ch.ServerSocketAdaptor.<init>(ServerSocketAdaptor.java:74)
        at java.base/sun.nio.ch.ServerSocketAdaptor.lambda$create$0(ServerSocketAdaptor.java:65)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
        at java.base/sun.nio.ch.ServerSocketAdaptor.create(ServerSocketAdaptor.java:67)
        at java.base/sun.nio.ch.ServerSocketChannelImpl.socket(ServerSocketChannelImpl.java:128)
        at java.base/sun.nio.ch.PipeImpl$Initializer$LoopbackConnector.run(PipeImpl.java:121)
        at java.base/sun.nio.ch.PipeImpl$Initializer.run(PipeImpl.java:76)
        at java.base/sun.nio.ch.PipeImpl$Initializer.run(PipeImpl.java:61)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
        at java.base/sun.nio.ch.PipeImpl.<init>(PipeImpl.java:171)
        at java.base/sun.nio.ch.SelectorProviderImpl.openPipe(SelectorProviderImpl.java:50)
        at java.base/java.nio.channels.Pipe.open(Pipe.java:155)
        at java.base/sun.nio.ch.WindowsSelectorImpl.<init>(WindowsSelectorImpl.java:142)
        at java.base/sun.nio.ch.WindowsSelectorProvider.openSelector(WindowsSelectorProvider.java:44)
        at java.base/java.nio.channels.Selector.open(Selector.java:295)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:160)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:214)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:227)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:231)
        at org.apache.kafka.clients.admin.KafkaAdminClient.createInternal(KafkaAdminClient.java:427)
        at org.apache.kafka.clients.admin.Admin.create(Admin.java:69)
        at org.apache.kafka.clients.admin.AdminClient.create(AdminClient.java:49)
        at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.createAdminClient(KafkaTopicProvisioner.java:239)
        at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.doProvisionConsumerDestination(KafkaTopicProvisioner.java:209)
        at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.provisionConsumerDestination(KafkaTopicProvisioner.java:181)
        at org.springframework.cloud.stream.binder.kafka.streams.KafkaStreamsBinderUtils.prepareConsumerBinding(KafkaStreamsBinderUtils.java:84)
        at org.springframework.cloud.stream.binder.kafka.streams.KStreamBinder.doBindConsumer(KStreamBinder.java:102)
        at org.springframework.cloud.stream.binder.kafka.streams.KStreamBinder.doBindConsumer(KStreamBinder.java:52)
        at org.springframework.cloud.stream.binder.AbstractBinder.bindConsumer(AbstractBinder.java:143)
        at org.springframework.cloud.stream.binding.BindingService.doBindConsumer(BindingService.java:169)
        at org.springframework.cloud.stream.binding.BindingService.bindConsumer(BindingService.java:115)
        at org.springframework.cloud.stream.binding.AbstractBindableProxyFactory.createAndBindInputs(AbstractBindableProxyFactory.java:112)
        at org.springframework.cloud.stream.binding.InputBindingLifecycle.doStartWithBindable(InputBindingLifecycle.java:58)
        at java.base/java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:647)
        at org.springframework.cloud.stream.binding.AbstractBindingLifecycle.start(AbstractBindingLifecycle.java:57)
        at org.springframework.cloud.stream.binding.InputBindingLifecycle.start(InputBindingLifecycle.java:34)
        at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182)
        at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53)
        at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360)
        at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158)
        at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122)
        at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:894)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
        at com.acme.receiver.ApplicationKt.main(Application.kt:88)
[Byte Buddy] ERROR sun.net.NetProperties [null, module java.base, loaded=false]
java.lang.IllegalArgumentException: Unsupported class file major version 58
        at reactor.blockhound.shaded.net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:195)
        at reactor.blockhound.shaded.net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:176)
        at reactor.blockhound.shaded.net.bytebuddy.jar.asm.ClassReader.<init>(ClassReader.java:162)
        at reactor.blockhound.shaded.net.bytebuddy.utility.OpenedClassReader.of(OpenedClassReader.java:82)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$Default.parse(TypePool.java:681)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$Default.doDescribe(TypePool.java:667)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$AbstractBase.describe(TypePool.java:408)
        at reactor.blockhound.shaded.net.bytebuddy.pool.TypePool$AbstractBase$Hierarchical.describe(TypePool.java:484)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$DescriptionStrategy$Default$3.apply(AgentBuilder.java:3582)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.resolve(AgentBuilder.java:10524)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.doTransform(AgentBuilder.java:10494)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10457)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.access$1500(AgentBuilder.java:10223)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:10907)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$Java9CapableVmDispatcher.run(AgentBuilder.java:10845)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer.transform(AgentBuilder.java:10413)
        at reactor.blockhound.shaded.net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer$ByteBuddy$ModuleSupport.transform(Unknown Source)
        at java.instrument/sun.instrument.TransformerManager.transform(TransformerManager.java:188)
        at java.instrument/sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:563)
        at java.base/java.net.SocketImpl.lambda$usePlainSocketImpl$0(SocketImpl.java:70)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:312)
        at java.base/java.net.SocketImpl.usePlainSocketImpl(SocketImpl.java:71)
        at java.base/java.net.SocketImpl.<clinit>(SocketImpl.java:67)
        at java.base/sun.nio.ch.ServerSocketAdaptor.<init>(ServerSocketAdaptor.java:74)
        at java.base/sun.nio.ch.ServerSocketAdaptor.lambda$create$0(ServerSocketAdaptor.java:65)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
        at java.base/sun.nio.ch.ServerSocketAdaptor.create(ServerSocketAdaptor.java:67)
        at java.base/sun.nio.ch.ServerSocketChannelImpl.socket(ServerSocketChannelImpl.java:128)
        at java.base/sun.nio.ch.PipeImpl$Initializer$LoopbackConnector.run(PipeImpl.java:121)
        at java.base/sun.nio.ch.PipeImpl$Initializer.run(PipeImpl.java:76)
        at java.base/sun.nio.ch.PipeImpl$Initializer.run(PipeImpl.java:61)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
        at java.base/sun.nio.ch.PipeImpl.<init>(PipeImpl.java:171)
        at java.base/sun.nio.ch.SelectorProviderImpl.openPipe(SelectorProviderImpl.java:50)
        at java.base/java.nio.channels.Pipe.open(Pipe.java:155)
        at java.base/sun.nio.ch.WindowsSelectorImpl.<init>(WindowsSelectorImpl.java:142)
        at java.base/sun.nio.ch.WindowsSelectorProvider.openSelector(WindowsSelectorProvider.java:44)
        at java.base/java.nio.channels.Selector.open(Selector.java:295)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:160)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:214)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:227)
        at org.apache.kafka.common.network.Selector.<init>(Selector.java:231)
        at org.apache.kafka.clients.admin.KafkaAdminClient.createInternal(KafkaAdminClient.java:427)
        at org.apache.kafka.clients.admin.Admin.create(Admin.java:69)
        at org.apache.kafka.clients.admin.AdminClient.create(AdminClient.java:49)
        at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.createAdminClient(KafkaTopicProvisioner.java:239)
        at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.doProvisionConsumerDestination(KafkaTopicProvisioner.java:209)
        at org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner.provisionConsumerDestination(KafkaTopicProvisioner.java:181)
        at org.springframework.cloud.stream.binder.kafka.streams.KafkaStreamsBinderUtils.prepareConsumerBinding(KafkaStreamsBinderUtils.java:84)
        at org.springframework.cloud.stream.binder.kafka.streams.KStreamBinder.doBindConsumer(KStreamBinder.java:102)
        at org.springframework.cloud.stream.binder.kafka.streams.KStreamBinder.doBindConsumer(KStreamBinder.java:52)
        at org.springframework.cloud.stream.binder.AbstractBinder.bindConsumer(AbstractBinder.java:143)
        at org.springframework.cloud.stream.binding.BindingService.doBindConsumer(BindingService.java:169)
        at org.springframework.cloud.stream.binding.BindingService.bindConsumer(BindingService.java:115)
        at org.springframework.cloud.stream.binding.AbstractBindableProxyFactory.createAndBindInputs(AbstractBindableProxyFactory.java:112)
        at org.springframework.cloud.stream.binding.InputBindingLifecycle.doStartWithBindable(InputBindingLifecycle.java:58)
        at java.base/java.util.LinkedHashMap$LinkedValues.forEach(LinkedHashMap.java:647)
        at org.springframework.cloud.stream.binding.AbstractBindingLifecycle.start(AbstractBindingLifecycle.java:57)
        at org.springframework.cloud.stream.binding.InputBindingLifecycle.start(InputBindingLifecycle.java:34)
        at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:182)
        at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:53)
        at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:360)
        at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:158)
        at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:122)
        at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:894)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
        at com.acme.receiver.ApplicationKt.main(Application.kt:88)
...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.