Open juergenzimmermann opened 5 years ago
Hi @juergenzimmermann,
I'm afraid that's due to https://bugs.openjdk.java.net/browse/JDK-8192936 and similar to #21 In JDK 13+, they adjusted the spec & impl and no longer allow redefining native methods :(
We will need to find an alternative way for 13+ and J9, meanwhile, they seem to plan adding a flag to keep the behaviour for a few versions: https://bugs.openjdk.java.net/browse/JDK-8192936?focusedCommentId=14254266&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-14254266
@bsideup When I use -XX:+AllowRedefinitionToAddDeleteMethods
the stacktrace goes away
@juergenzimmermann thanks a lot for trying it! I will keep this issue open as a reminder to document this flag 👍
Heaving quite different behavior on Oracle JDK 13 in Windows: it does not throw an error about blocking call until I add this flag
Still reproduced with JDK 14.0.1 and BlockHound 1.0.3
Using Blockhound 1.0.4 and JDK 14.0.2 and specify the following in surefire plugin worked:
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<argLine>-XX:+AllowRedefinitionToAddDeleteMethods</argLine>
</configuration>
</plugin>
...
</plugins>
any way this can be added to gradle?
@abdullahumer sure:
tasks.withType(Test).all {
if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_13)) {
jvmArgs += [
"-XX:+AllowRedefinitionToAddDeleteMethods"
]
}
}
Thanks! @bsideup
Still reproduced with JDK 15.0.2 and BlockHound 1.0.6.RELEASE. "-XX:+AllowRedefinitionToAddDeleteMethods" option still shows deprecation warning. Any updates?
Using Blockhound 1.0.4 and JDK 14.0.2 and specify the following in surefire plugin worked:
<plugins> ... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <argLine>-XX:+AllowRedefinitionToAddDeleteMethods</argLine> </configuration> </plugin> ... </plugins>
In my case Using Blockhound 1.0.6 and JDK 15.0.6, worked
Using blockhound 1.0.6 and JDK 16.0.2 I am still getting this error and has to use the flag...
Hi. As far as I understand, according to https://bugs.openjdk.org/browse/JDK-8221528.
"This option (AllowRedefinitionToAddOrDeleteMethods) is deprecated right away. The plan is to keep it for a couple of releases to allow customers (tool vendors) to remove dependency on old behavior from their tools."
Do you plan BlockHound work according to the new JVM TI behavior?
I guess that if this issue is not solved, when the option AllowRedefinitionToAddOrDeleteMethods
is removed from JVM, then Blockhound is completely unusable, right?
Now in 2023, almost four years after the original issue, would it be possible to have a fix without the -XX workaround please?
I will take a look, but I don't promise anything for the moment, because looking at the history of this issue, without the work around flag, it seems to be a very very big deal to redefine / retransform classes (add/delete private static and private final instance methods in the new class versions).
so, I'm afraid that for the moment, we need to continue using -XX:+AllowRedefinitionToAddDeleteMethods
for JDK13+
Is there any issues if you continue using this flag for the moment ?
thanks.
i am using Java 17 and Spring 3.1.3, even after including the -XX:+AllowRedefinitionToAddDeleteMethods
flag, i am still facing the error. Is the flag removed from JVM or has the fix stopped working?
Hi @divyanshsaini1805 ,
please open a separate issue with a reproducer project; From my side, I did the following which worked for me using Spring 3.1.3, and java 17:
build.gradle:
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.3'
id 'io.spring.dependency-management' version '1.1.3'
}
apply plugin: 'application'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'io.projectreactor.netty:reactor-netty-core:1.0.37'
implementation 'io.projectreactor.netty:reactor-netty-http:1.0.37'
implementation('io.projectreactor.tools:blockhound:1.0.8.RELEASE')
implementation 'javax.annotation:javax.annotation-api:1.3.2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
task(echoServer, dependsOn: 'classes', type: JavaExec) {
main = 'com.example.EchoServer'
classpath = sourceSets.main.runtimeClasspath
args ''
systemProperty "io.netty.leakDetectionLevel", "DISABLED"
debugOptions {
enabled = false
port = 5005
server = true
suspend = true
}
}
DemoApplication.java:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Demo.java:
package com.example.demo;
import org.springframework.stereotype.Component;
import reactor.blockhound.BlockHound;
import reactor.netty.tcp.TcpServer;
import javax.annotation.PostConstruct;
@Component
public class Demo {
static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));
@PostConstruct
public void init() {
System.out.println("Jdk version used: " + System.getProperty("java.version"));
BlockHound.install();
TcpServer server =
TcpServer.create()
.port(PORT)
.handle((in, out) -> {
try {
Thread.sleep(100);
} catch (Throwable err) {
err.printStackTrace();
}
return out.send(in.receive().retain());
});
server.bindNow()
.onDispose()
.block();
}
}
then, from one console using java17:
./gradlew build
java -XX:+AllowRedefinitionToAddDeleteMethods -jar build/libs/demo-0.0.1-SNAPSHOT.jar
from another console:
curl -v http://localhost:8080/foo
this will display the following from the first console:
reactor.blockhound.BlockingOperationError: Blocking call! java.lang.Thread.sleep
at java.base/java.lang.Thread.sleep(Thread.java)
at com.example.demo.Demo.lambda$init$0(Demo.java:34)
at reactor.netty.tcp.TcpServer$OnConnectionHandle.accept(TcpServer.java:277)
at reactor.netty.tcp.TcpServer$OnConnectionHandle.accept(TcpServer.java:264)
at reactor.netty.transport.ServerTransportConfig$ServerTransportDoOnConnection.onStateChange(ServerTransportConfig.java:253)
at reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:481)
at reactor.netty.channel.ChannelOperationsHandler.channelActive(ChannelOperationsHandler.java:62)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:262)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:238)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:231)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelActive(DefaultChannelPipeline.java:1398)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:258)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:238)
at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:895)
at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:522)
at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:429)
at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:486)
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
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:833)
Thanks.
I have tried on windows with corretto-17 and temurin-17. When I add the vm option to the Surefire plugin config in pom.xml, my unit tests work with BlockHound. But when I add the vm option to my IntelliJ run configuration or in the vm options file I still see this error when I start up my springboot app:
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalStateException: The instrumentation have failed.
It looks like you're running on JDK 13+.
You need to add '-XX:+AllowRedefinitionToAddDeleteMethods' JVM flag.
public static void main(String[] args) {
System.out.println(args[0] + " ");
SpringApplication.run(BillGenerationServiceApplication.class, args);
}
I see this: -XX:+AllowRedefinitionToAddDeleteMethods
at the top of the console.
Any ideas? Thanks.
Hi @divyanshsaini1805 ,
please open a separate issue with a reproducer project; From my side, I did the following which worked for me using Spring 3.1.3, and java 17:
build.gradle:
plugins { id 'java' id 'org.springframework.boot' version '3.1.3' id 'io.spring.dependency-management' version '1.1.3' } apply plugin: 'application' group = 'com.example' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter' implementation 'io.projectreactor.netty:reactor-netty-core:1.0.37' implementation 'io.projectreactor.netty:reactor-netty-http:1.0.37' implementation('io.projectreactor.tools:blockhound:1.0.8.RELEASE') implementation 'javax.annotation:javax.annotation-api:1.3.2' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() } task(echoServer, dependsOn: 'classes', type: JavaExec) { main = 'com.example.EchoServer' classpath = sourceSets.main.runtimeClasspath args '' systemProperty "io.netty.leakDetectionLevel", "DISABLED" debugOptions { enabled = false port = 5005 server = true suspend = true } }
DemoApplication.java:
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
Demo.java:
package com.example.demo; import org.springframework.stereotype.Component; import reactor.blockhound.BlockHound; import reactor.netty.tcp.TcpServer; import javax.annotation.PostConstruct; @Component public class Demo { static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); @PostConstruct public void init() { System.out.println("Jdk version used: " + System.getProperty("java.version")); BlockHound.install(); TcpServer server = TcpServer.create() .port(PORT) .handle((in, out) -> { try { Thread.sleep(100); } catch (Throwable err) { err.printStackTrace(); } return out.send(in.receive().retain()); }); server.bindNow() .onDispose() .block(); } }
then, from one console using java17:
./gradlew build java -XX:+AllowRedefinitionToAddDeleteMethods -jar build/libs/demo-0.0.1-SNAPSHOT.jar
from another console:
curl -v http://localhost:8080/foo
this will display the following from the first console:
reactor.blockhound.BlockingOperationError: Blocking call! java.lang.Thread.sleep at java.base/java.lang.Thread.sleep(Thread.java) at com.example.demo.Demo.lambda$init$0(Demo.java:34) at reactor.netty.tcp.TcpServer$OnConnectionHandle.accept(TcpServer.java:277) at reactor.netty.tcp.TcpServer$OnConnectionHandle.accept(TcpServer.java:264) at reactor.netty.transport.ServerTransportConfig$ServerTransportDoOnConnection.onStateChange(ServerTransportConfig.java:253) at reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:481) at reactor.netty.channel.ChannelOperationsHandler.channelActive(ChannelOperationsHandler.java:62) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:262) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:238) at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:231) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelActive(DefaultChannelPipeline.java:1398) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:258) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:238) at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:895) at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:522) at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:429) at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:486) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174) at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167) at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) 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:833)
Thanks.
hi, i know it's been a super long time, but since this thread is a lot active, i would like to add my part, for Spring 3.1.3, and java 17, the -XX:+AllowRedefinitionToAddDeleteMethods flag works good indeed if used with the following command: java -XX:+AllowRedefinitionToAddDeleteMethods -jar target/Required_jar_file.jar,
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: