我的应用程序中有一个关闭钩子(使用Runtime.getRuntime().addShutdownHook
创建)。但是,如果我从Eclipse中启动应用程序,当它关闭时,关闭挂钩不会执行。
我认为这是因为Eclipse向进程发送了等效的强制终止信号,这不会导致关闭挂钩执行(相当于Windows上的taskkill / F或Linux上的kill -p),虽然我不是很确定。
有谁知道怎么解决这个问题?我正在运行Windows(Vista),我觉得这可能是Windows特有的问题,但我不确定。
答案 0 :(得分:23)
我在主要方法结束时使用了以下hack来解决问题:
if (Boolean.parseBoolean(System.getenv("RUNNING_IN_ECLIPSE"))) {
System.out.println("You're using Eclipse; click in this console and " +
"press ENTER to call System.exit() and run the shutdown routine.");
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
System.exit(0);
}
答案 1 :(得分:12)
首先,你的申请结束还是强行结束?如果你强行结束它(通过停止按钮),这个Eclipse bug report会详细说明为什么这可能不起作用。
如果不这样做,您可能会认为这是特定于Windows的行为。我在Mac上,所以我无法确认,抱歉。但是,我可以告诉您,以下测试程序 按预期执行关闭挂钩。
public class MyShutdownHook
{
public static void main( String[] args )
{
System.out.println( "Entering main." );
Runtime.getRuntime().addShutdownHook(
new Thread(
new Runnable() {
public void run() {
System.out.println( "Shutdown hook ran." );
}
}
)
);
System.out.println( "Exiting main." );
}
}
Runtime#addShutdownHook的Javadocs确实提到当JVM中止而没有正常退出时,关闭挂钩不会运行,所以再一次,你的假设可能是正确的。话虽这么说,这里有一些事情要尝试。再次,抱歉,我无法提前确认这些 - 这里没有Windows。 (幸好!)
答案 2 :(得分:5)
这是一个可以在eclipse之外运行的脚本,列出在Eclipse下运行的可用进程,你可以杀掉它。
#!/bin/bash
set -o nounset # Treat unset variables as an error
PROCESSES=$(ps axo pid,ppid,command)
# Find eclipse launcher PID
LAUNCHER_PID=$(echo "$PROCESSES" | grep "/usr/lib/eclipse/eclipse" |grep -v "launcher"|awk '{print $1}')
echo "Launcher PID $LAUNCHER_PID"
# Find eclipse PID
ECLIPSE_PID=$(echo "$PROCESSES" | egrep "[[:digit:]]* $LAUNCHER_PID " | awk '{print $1}')
echo "Eclipse PID $ECLIPSE_PID"
# Find running eclipse sub-process PIDs
SUB_PROCESS=$(echo "$PROCESSES" | egrep "[[:digit:]]* $ECLIPSE_PID " | awk '{print $1}')
# List processes
echo
for PROCESS in $SUB_PROCESS; do
DRIVER=$(ps --no-headers o pid,ppid,command $PROCESS | awk '{print $NF}')
echo "$PROCESS $DRIVER"
done
echo "Kill a process using: 'kill -SIGTERM \$PID'"
答案 3 :(得分:1)
我不知道如何解决这个问题,但是IntelliJ在他们的“运行”对话框中添加了一个单独的按钮,该对话框将以调用Shutdown Hooks的方式关闭VM。他们的调试器没有此功能。
答案 4 :(得分:1)
在Windows上以标准方式正常停止java应用程序,您需要向其发送 Ctrl + C 。这仅适用于控制台应用程序,但Eclipse使用javaw.exe
而不是java.exe
。要解决此问题,请打开启动配置,JRE选项卡并选择“Alternative JRE:”。将出现“Java可执行文件”组框,并允许输入备用可执行文件“java”。
现在我们需要一个外部程序将Ctrl-C发送到带有隐藏控制台的进程。我找到了提示here和here。我们的程序附加到所需进程的控制台并发送控制台事件。
#include <stdio.h>
#include <windows.h>
int main(int argc, char* argv[])
{
if (argc == 2) {
unsigned pid = 0;
if (sscanf_s(argv[1], "%u", &pid) == 1) {
FreeConsole(); // AttachConsole will fail if we don't detach from current console
if (AttachConsole(pid)) {
//Disable Ctrl-C handling for our program
SetConsoleCtrlHandler(NULL, TRUE);
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
return 0;
}
}
}
return 1;
}
测试java程序:
public class Shuthook {
public static void main(final String[] args) throws Exception {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Shutting down...");
}
});
String sPid = ManagementFactory.getRuntimeMXBean().getName();
sPid = sPid.substring(0, sPid.indexOf('@'));
System.out.println("pid: " + sPid);
System.out.println("Sleeping...");
Thread.sleep(1000000);
}
}
终止它:
C:\>killsoft.exe 10520
Eclipse中的测试程序输出:
pid: 10520
Sleeping...
Shutting down...
答案 5 :(得分:0)
此刻我陷入了网络圈,并没有看到我在寻找什么。 但我确实记得eclipse有一个与在同一个VM中启动应用程序相关的运行配置选项。 您是否可以在与eclipse VM相同的VM中启动Java应用程序?
但这个选项让我不知所措。
答案 6 :(得分:0)
Sairam就在这里,通过调用 System.exit(0),我们可以终止eclipse JVM,并且可以看到Shutdown钩子结果