【问题标题】:Can't debug Java Windows Services with jhat, jps, jstack无法使用 jhat、jps、jstack 调试 Java Windows 服务
【发布时间】:2010-11-14 22:29:19
【问题描述】:

我经常向 Linux 和 Mac 上的开发人员展示 jhat、jps 和 jstack 工具集。但是,最近一位开发人员表示,如果所讨论的 Java 应用程序以 Windows Service 运行,则这些在 Windows 中是不可用的。

Sun-filed bug says something very similar,但由于不活动而关闭。

我已经亲自测试过了,确实它看起来是真的,尽管我简直不敢相信。这是设置:

  1. Tomcat 或类似的以“登录身份”==“本地系统”作为 Windows 服务运行
  2. 具有管理员权限的用户登录到同一台 Windows 计算机。
  3. 管理员打开 Windows 任务管理器,可以看到 java.exe 正在运行
  4. 管理员打开控制台,输入“jps”,获取不包括 Tomcat 的 java 服务进程的进程列表。
  5. 作为蛮力尝试,从 Windows 任务管理器获取 tomcat 的 PID 作为服务。键入 jstack 。得到回复:没有这个进程

这在 Windows XP、Windows 2003 Server 和 Windows 7 下似乎可以重现。Java 版本 1.5 和 1.6 产生相同的结果。

是否有办法从终端(即使以管理员身份登录)“sudo up”以获取 JPS 和其他工具以查看 java 服务?

【问题讨论】:

  • 您是否尝试过(或者是否可以选择)使用远程管理选项而不是 PID 进行连接?
  • 我们可能不得不求助于——在服务执行程序中设置一个 jstatd 以通过套接字公开 java 进程——但目标只是通过 PID 来完成。我只是想确认我在这里没有遗漏任何东西。这对于 Windows 来说似乎是一个巨大的障碍,但在 Mac/BSD/Linux 上却不是问题。
  • Devon_C_Miller 的回答是否为您解决了这个问题?我以 SYSTEM 身份运行 jconsole,但这并没有消除问题(请参阅我对 Devon_C_Miller 的回答的评论)

标签: java windows windows-services


【解决方案1】:

您只会获得那些“属于”您的进程 - 相同的用户 ID。

你能用 jvisualvm 连接到它吗?

【讨论】:

  • 也无法使用 jvisualvm 访问进程。显然 jps 和 jvisualvm 使用相同的底层 lib/api 进行询问(jvmstat)
【解决方案2】:

我很幸运地通过在命令提示符下运行由 SYSTEM 用户运行的进程来调试:

c:> time/t
11:18 AM
c:> at 11:19 /interactive cmd.exe
Added a new job with job ID = 1

使用未来 1 分钟的时间。当“at”作业运行时,将打开以用户 SYSTEM 身份运行的 Windows 命令提示符。从那里您应该能够看到 java 进程。

如果服务以本地用户身份运行(通过双击服务并选择“登录”选项卡从“mmc %windir%\system32\SERVICES.MSC”中查看详细信息),您可以执行相同的操作使用“runas”:

runas /user:USERNAME cmd.exe

【讨论】:

【解决方案3】:

我只发现一个建议将 visuamvm(或其他工具)作为 Windows 服务运行:Monitoring Java Processes Running As a Windows Service

也许其他人知道更好的解决方案。

【讨论】:

    【解决方案4】:

    要让实用程序运行,您可以使用登录帐户使用“mstsc /admin”连接到控制台会话(不确定它需要拥有的确切权限,我的是在管理员组中)并使用 Sysinternals psexec 工具作为系统运行。下面是一个使用 jstack.exe 的例子:

    psexec -s "%JAVA_HOME%\bin\jstack.exe" PID >stack.txt
    其中 PID 是您的进程的进程 ID。根据您的特定环境,您可能还必须替换 JDK 的实际路径。

    另外,TEMP directory must be set correctly 或这些工具也将不起作用。

    【讨论】:

      【解决方案5】:

      这是我记录线程转储的批处理文件:

      :: Creates a thread dump for the tomcat6.exe process saved in a timestamped filename and views it!
      :: Jim Birch 20111128 rev 2015-10-12
      
      ::Note this required the following files to be placed in the confluence jre/bin folder:
      :: 
      :: attach.dll  - From the Java JDK  (must be the same version)
      :: tools.jar   - ditto
      :: psexec.exe  - from Windows sysinternals
      :: Also, the TEMP directory must be set (stack overflow)
      set TEMP=c:\windows\temp
      
      ::go to run location
      d:
      cd \confluence.application\jre\bin
      
      ::build datetime filename
      rem datetime from wmi.exe
      for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set dt0=%%I
      rem  datetime string as YYYY-MM-DD-hhmmss
      set dt=%dt0:~0,4%-%dt0:~4,2%-%dt0:~6,2%-%dt0:~8,6%
      set ff=td-%dt%.txt
      echo filename: %ff%
      
      ::tomcat PID   
      FOR /F "tokens=2" %%I in ('TASKLIST /NH /FI "IMAGENAME eq tomcat6.exe"' ) DO SET PID=%%I
      ECHO pid: %PID%
      
      ::combine above with jstack command (won't work without psexec)
      psexec -s "D:\confluence.application\jre\bin\jstack.exe" -l %PID%  >>  %ff%
      
      :: view output txt file
      start %ff%
      
      ::pause to review script operation, or use ping to wait a few secs 
      ::ping localhost -n 20 >nul
      pause
      

      【讨论】:

        【解决方案6】:

        这是最终对我有用的解决方案,用于从终端会话中不同用户下运行的未准备好的 java 进程或作为 Windows 服务获取堆栈跟踪。

        jstack.cmd

        @for /f "usebackq tokens=2" %%I in (`tasklist /NH /FI "imagename eq tomcat.exe" /FI "username eq SYSTEM"`) DO set PID=%%I
        @for /f "tokens=2 delims==." %%G in ('wmic os get localdatetime /value') do @set datetime=%%G
        @set date_time=%datetime:~0,4%_%datetime:~4,2%_%datetime:~6,2%__%datetime:~8,2%_%datetime:~10,2%_%datetime:~12,2%
        PsExec.exe /accepteula -h -s -d cmd /c "%JAVA_HOME%\jstack.exe" -l %PID% ^>"%~dp0jstack_%date_time%.txt"
        

        第一行determines进程名和用户的PID。

        然后PsExecaccepted EULA 有助于在elevated mode 中调用jstackproperly escapedoutput 重定向到jstack*.txt 脚本目录中的timestamp included in file name 文件。

        您可能需要事先将 PsExec 和 JDK 目录添加到 PATH

        我之前曾尝试通过 SendSignal 强制执行线程转储,但它从未可靠地与 Windows 服务进程一起工作。

        【讨论】:

        • 可以不使用WMIC获取datetime值,如下: set DATETIME=%date:~10,4%-%date:~4,2%-%date:~7,2%_ %time:~0,2%-%time:~3,2%-%time:~6,2%(可能需要根据您的 Windows 区域设置进行调整)。此外,可能需要更改令牌值以从任务列表输出中获取 PID。最后,批处理文件所在的 %~dp0 文件夹不能包含任何空格。以管理员身份运行批处理文件。
        【解决方案7】:

        对于jconsole 等基于GUI 的工具,请在tomcat 中启用JMX 支持,并通过JMX 连接。

        对于命令行工具,例如jpsjstat,请在管理控制台中运行以下命令。注意:最好将psexec 路径和%JAVA_HOME%\bin 添加到PATH 环境中。

        psexec -S cmd.exe
        

        在我们得到一个新的console后,我们可以运行jpsjstat或其他工具到"debug"tomcat作为windows服务使用本地系统帐户运行。

        e:\sde\PSTools>jps
        7408 Jps
        
        e:\sde\PSTools>psexec -s cmd
        
        PsExec v2.2 - Execute processes remotely
        Copyright (C) 2001-2016 Mark Russinovich
        Sysinternals - www.sysinternals.com
        
        
        Microsoft Windows [Version 6.2.9200]
        (c) 2012 Microsoft Corporation. All rights reserved.
        
        C:\windows\system32>jps
        9792 Jps
        8812
        
        C:\windows\system32>jstat -gc 8812
         S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     G
        CT
        10752.0 10752.0  0.0   10744.3 65536.0  21751.1   175104.0    3730.9   17792.0 17138.5 2176.0 1974.8      1    0.034   0      0.00
        0    0.034
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多