org.codehaus.mojo:exec-maven-plugin:3.3.0
插件“java”目标文档指出“一旦所有已知的非守护线程退出,守护线程就会加入并中断”。这不是我在涉及 RMI 线程的一些代码中观察到的情况(除了我不知道什么是“未知”线程),我想知道为什么。这是一个错误,还是我错过了什么?
我的“服务器”程序启动一个非守护线程(通过 RMI),当我使用“java”目标运行它时,JVM 在到达
main
方法末尾时退出。由于非守护线程仍在运行,我预计它会继续运行。当我使用直接调用 java
运行它时,正如预期的那样,即使在 main
完成后,程序也会继续运行。
这是服务器。
public class Server {
public static void main(String[] args) throws Exception {
Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
RemoteTest engine = new RemoteTestImpl();
RemoteTest stub = (RemoteTest) UnicastRemoteObject.exportObject(engine, 0);
registry.rebind("RemoteTestJ2", stub);
Thread.sleep(3000);
Thread.getAllStackTraces().keySet().forEach(thread -> {
System.out.println("Thread: " + thread.getName() + " is daemon: " + thread.isDaemon());
});
}
}
这是客户。
public class User {
public static void main(String[] args) throws Exception {
Registry registry = LocateRegistry.getRegistry(Registry.REGISTRY_PORT);
RemoteTest rem = (RemoteTest) registry.lookup("RemoteTestJ2");
while(true) {
System.out.println("Tested: " + rem.test(0, 1));
}
}
}
完整代码在这里。
git clone https://github.com/oliviercailloux/JGradLib-Additioner.git ; cd JGradLib-Additioner ; git checkout rmistop
mvn -Dexec.mainClass=io.github.oliviercailloux.javagrade.graders.Server compile org.codehaus.mojo:exec-maven-plugin:3.3.0:java
。java -cp "target/classes/" io.github.oliviercailloux.javagrade.graders.User
。预期:RMI 机制在后台启动非守护线程并阻止 JVM 退出,以便服务器无限期地保持活动状态,并且客户端永远打印
test
调用的结果。
实际:服务器启动,RMI 按预期启动非守护线程(以及守护线程),服务器休眠三秒,打印其线程,然后退出。与此同时,客户端开始向终端发送
test
调用的结果,但三秒后,崩溃并显示堆栈跟踪,抱怨它无法再到达远程端。
exec
插件和RMI方面似乎都需要触发这种奇怪的行为。
如果使用
java -cp "target/classes/" io.github.oliviercailloux.javagrade.graders.Server
而不是 exec
插件运行服务器,服务器将按预期运行。
或者,如果我更改服务器代码以简单地启动一个保持忙碌的新线程(在 while 循环中休眠),服务器将继续按预期运行。
不要使用
exec:java
,使用exec:exec
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.oliviercailloux.grading</groupId>
<artifactId>additioner</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<!--
<maven.compiler.release>17</maven.compiler.release>
-->
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>run-java-program</id> <!-- Unique identifier for this execution -->
<phase>custom-phase</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<workingDirectory>${project.directory}</workingDirectory>
<arguments>
<argument>-Dsun.rmi.transport.tcp.logLevel=VERBOSE</argument>
<argument>-Dsun.rmi.transport.logLevel=VERBOSE</argument>
<argument>-classpath</argument>
<classpath/>
<!-- Replace with your main class -->
<argument>io.github.oliviercailloux.javagrade.graders.Server</argument>
<!-- Replace with your program arguments -->
<!--
<argument>arg1</argument>
<argument>arg2</argument>
-->
<!-- Add more arguments as needed -->
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</project>
mvn clean package exec:exec
您的服务器可以删除
Thread.sleep(3000);
Thread.getAllStackTraces().keySet().forEach(thread -> {
System.out.println("Thread: " + thread.getName() + " is daemon: " + thread.isDaemon());
});