如何获取closures钩子从Eclipse启动的进程上执行

我在我的应用程序(使用Runtime.getRuntime().addShutdownHook )创build一个closures挂钩。 但是,如果我从Eclipse内部启动应用程序,closures挂钩时不执行。

我认为这是因为Eclipse向进程发送了相当于强制kill信号的过程,不会导致执行closures挂钩(相当于Windows上的taskkill / F或者kill Linux上的-p)我不太确定。

有谁知道如何解决这个问题? 我正在运行Windows(Vista),我觉得这可能是Windows特有的问题,但我不确定。

我在主要方法的末尾使用了下面的黑客来解决这个问题:

 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); } 

首先,你的应用程序是结束还是你强行结束? 如果你强制结束它(通过停止button),这个Eclipse错误报告详细说明了为什么这可能不工作。

否则,你可能是正确的这是特定于Windows的行为。 我在Mac上,所以我不能确认,对不起。 但是,我可以告诉你,下面的testing程序按照预期执行closures挂钩。

 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." ); } } 

运行时#addShutdownHook的Javadocs提到,当JVM被中止,不能正常退出时,closures钩子不会运行,所以你的假设可能是正确的。 这就是说,这里有一些事情要尝试。 再次,对不起,我不能提前确认这些 – 这里没有Windows。 (幸好!)

  • 确保JVM不包含-Xrs选项。 这对关机挂钩有副作用 。
  • 尝试使用-server-client选项启动JVM。 根据我的经验,边缘情况行为可以通过VM模式的select来实现。 (尤其是关于线程 – 至less在Mac上)
  • 你是否在探查器或类似的地方启动你的应用程序? 加载任何本地库?
  • 你是否得到了一些致命的错误,错过了? 例如,OutOfMemoryError之类的?
  • 尝试在Eclipse中检查/取消选中应用程序的“运行configuration”对话框中的 启动后台”选项。
  • 最后但并非最不重要:如果有机会,手动调用System.exit() 。 🙂

这里有一个你可以在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'" 

我不知道如何解决这个问题,但IntelliJ在他们的“运行”对话框中添加了一个单独的button,这将以closures挂钩的方式closures虚拟机。 他们的debugging器没有这个function。

目前我陷入了websphere,并没有看到我在找什么。 但是我确实记得eclipse有一个运行configuration选项,与在同一个VM中启动应用程序相关。 是否有可能在与eclipse VM相同的虚拟机中启动Java应用程序?

但是,这个select滑倒我的头脑。

Sairam就在这里,通过调用System.exit(0)我们可以终止Eclipse的JVM,并且可以看到closures钩子的结果

在Windows上以标准方式正常停止Java应用程序,您需要发送Ctrl + C。 这只适用于控制台应用程序,但Eclipse使用javaw.exe而不是java.exe 。 为了解决这个问题,打开启动configuration,JRE选项卡并select“Alternative JRE:”。 出现“Java可执行文件”组框,并允许input备用可执行文件“java”。

现在我们需要一个外部程序来发送Ctrl-C到一个隐藏控制台的进程。 我在这里和这里find了提示。 我们的程序附加到所需进程的控制台并发送控制台事件。

 #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; } 

testingjava程序:

 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中testing程序输出:

 pid: 10520 Sleeping... Shutting down... 

我知道我晚了一点,但我发现这个线索寻求帮助,其他人可能也会这样。

我们遇到了同样的问题,并使用Eclipse插件 (在Linux上)解决了这个问题,该插件提供了额外的停止button。 我希望这能为你们所有人以及它帮助我们:)