【问题标题】:cannot start jstatd due to permission error由于权限错误无法启动 jstatd
【发布时间】:2012-03-30 08:58:15
【问题描述】:

我尝试在linux机器上运行jstatd jvm监控工具

jboss@hostAddr:/usr/java/jdk1.6.0_18/bin> uname -a
Linux hostAddr 2.6.16.60-0.34-smp #1 SMP Fri Jan 16 14:59:01 UTC 2009 x86_64 x86_64 x86_64 GNU/Linux

使用以下命令:

jstatd -J-Djava.security.policy=~/jstatd.all.policy

jstatd.all.policy 内容

grant codebase "file:${java.home}/../lib/tools.jar" {

   permission java.security.AllPermission;

};

不幸的是,我得到以下输出:

Could not create remote object
access denied (java.util.PropertyPermission java.rmi.server.ignoreSubClasses write)
java.security.AccessControlException: access denied (java.util.PropertyPermission java.rmi.server.ignoreSubClasses write)
        at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
        at java.security.AccessController.checkPermission(AccessController.java:546)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
        at java.lang.System.setProperty(System.java:725)
        at sun.tools.jstatd.Jstatd.main(Jstatd.java:122)

由于某种原因,jstatd 在具有相同命令和策略文件的 Windows 上成功运行。

Linux java 版本:

java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode)

Windows java 版本:

java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)

【问题讨论】:

标签: java jvm


【解决方案1】:

刚刚找到以下脚本来运行jstatd。我设法用这个脚本运行jstatd https://gist.github.com/nicerobot/1375032

#!/bin/sh
policy=${HOME}/.jstatd.all.policy
[ -r ${policy} ] || cat >${policy} <<'POLICY'
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
POLICY

jstatd -J-Djava.security.policy=${policy} &

【讨论】:

  • @michael nesterenko,无法使用 service:jmx:rmi:///jndi/rmi://XXXXXX:8091/jmxrmi 连接到 XXXXXXXX:8091 我收到此错误,可能是什么问题?
  • 嗨,迈克尔。您的解决方案对我来说效果很好 - 由于我在其他一些帖子中读到的内容,我只将策略文件的路径更改为硬编码路径。我想知道当 jstatd 在后台使用 & 运行时如何停止它。我试过 ps -x 来查看我是否看到了该进程,但我没有,即使它正在运行,因为 Visual VM 可以连接到它。如果您对完成后如何终止该进程有任何想法,请告诉我。
  • 天啊!我以 root 身份启动进程,因此我需要执行“sudo su”才能使进程出现在列表中。
【解决方案2】:

这对我有用:

  1. 确保 tools.jar 文件存在并且运行 jstatd 命令的用户有权读取它。

  2. 确保jstatd.all.policy 中指向 tools.jar 的 URL 正确并声明了协议(在本例中为文件)。例如,根据java.home 变量指向的位置,您可能需要像这样删除路径中的../ 部分(我必须这样做):

    grant codebase "file:${java.home}/lib/tools.jar" {
       permission java.security.AllPermission;
    };
    
  3. 从 Java 1.4 开始,策略文件需要在没有 BOM 的情况下以 UTF-8 编码。 EOL(CRLF vs LF)应该无关紧要。有关更多信息,请参阅 Oracle 的“默认策略实施和策略文件语法”文档,在“更改”部分下(未提供链接,因为我没有足够的声誉点来发布超过 2 个链接,但我确定你就能找到那个文件)。

  4. 运行 jstatd 命令时使用策略文件的绝对路径,例如

    jstatd -p 12345 -J-Djava.security.policy=/absolute-path-to/jstatd.all.policy
    

    编辑:-J 参数在 Java 1.8 中可能不再需要或支持,因此该命令将改为:

    jstatd -p 12345 -Djava.security.policy=/absolute-path-to/jstatd.all.policy
    

    (感谢@lisak 指出这一点)

  5. 最后,一旦你通过了这一点,你可能会发现其他问题(我做到了),这些帖子为我指明了正确的方向:Using VisualVM to monitor a remote JBoss instanceRemote Profiling of JBoss using VisualVM。基本上,如果 1099 已在使用中,您可能需要使用 -p 参数来使用不同的端口,并通过 JAVA_OPTS 在 JBoss run.conf 中添加一些 java 选项(假设您正在监视 JBoss 实例)。在提供的链接中更详细地解释了所有内容。

编辑: - 将死链接Using VisualVM to monitor a remote JBoss instance 指向另一个具有相同内容的页面。

【讨论】:

  • 在我的情况下,一些 ${java.home} 或 ${JAVA_HOME} 不起作用。我必须指定 tools.jar 的完整绝对路径。
  • 我不得不在策略文件和 shell 命令中都使用绝对路径。
  • @lisak,抱歉,我将您删除的 -J 放回参数 -J-Djava.security.policy=/absolute-path-to/jstatd.all.policy 中,因为这就是 jstatd documentation from Oracle 的含义。您是否找到了不属于这种情况的环境或 jstatd 版本?
  • 恕我直言,java 1.8 不再支持它,至少它对我不起作用,据我所知,即使在 java 1.7 上,它也可以在没有 -J 的情况下工作......
  • 我在 Windows 7 上的 Java 1.7 中尝试不使用 -J,但它似乎不起作用。我已经在 J​​ava 1.5 和 Solaris 5.10 的 1.6 上成功使用了 -J。如果 Java 1.8 不再支持它,也许我们应该添加一个注释,但保留 -J,因为它可能在其他版本或平台中需要。
【解决方案3】:

使用process substitution 的单行符(虽然是bashism):

jstatd -p 1099 -J-Djava.security.policy=<(echo 'grant codebase "file:${java.home}/../lib/tools.jar" {permission java.security.AllPermission;};')

包装:

jstatd -p 1099 -J-Djava.security.policy=&lt;(echo 'grant codebase "file:${java.home}/../lib/tools.jar" {permission java.security.AllPermission;};')

截至jdk1.8.0_92,java 启动器选项前缀-J 仍然是必需的。

注意:

原始问题更可能是由于~/jstatd.all.policy 中的波浪号~ 未扩展因此无法被java 理解,同时绝对路径或使用${HOME} 应该可以工作。

【讨论】:

  • 值得注意的是,lib 目录直接位于 JDK 根目录下,因此该路径可能不应该有 ..。我用file:${JAVA_HOME}/lib/tools.jar
【解决方案4】:

我有同样的问题,你应该怎么做:

  1. 确保javac 在您的$PATH 中
  2. 在运行 jstatd 时指定策略文件的完整(绝对)路径
    jstatd -J-Djava.security.policy=/path/to/jstatd.all.policy

这对我有帮助。

【讨论】:

    【解决方案5】:

    您是否指定了错误的路径(我是)?

    尝试将策略放入 /tmp/jstatd.all.policy 然后运行:

    jstatd -J-Djava.security.policy=/tmp/jstatd.all.policy
    

    【讨论】:

    • 我认为没有必要将其放入/tmp,只要确保文件名正确即可。我不小心将我的 jstatd.policy.all 命名为不匹配。
    【解决方案6】:

    关于以前的答案的补充一点,我花了一些时间来弄清楚。
    当我在策略文件 ${java.home}/lib/tools.jar 中使用相对路径时,它实际上将 jstatd 指向 JAVA_HOME/jre/ 目录,并且由于我安装了 jdk,因此我不得不使用 ${java.home}/../lib/tools.jar 来到达正确的位置。

    编辑我在一个运行带有 jdk 8 的 ubuntu 的 docker 容器中运行 jstatd(正确设置了 JAVA_HOME)。

    【讨论】:

      【解决方案7】:

      如果您使用的是 Java 11,则需要查看此答案:Starting jstatd in Java 9+ - Stack Overflow
      策略文件是这样的:

      grant codebase "jrt:/jdk.jstatd" {    
         permission java.security.AllPermission;    
      };
      

      【讨论】:

        【解决方案8】:

        @michael nesterenko 的回答很好。

        但是如果有时即使你已经启动了 Jstatd 也无法连接服务器,你可以尝试分配 'rmi.server.hostname'

        #!/bin/sh
        policy=${HOME}/.jstatd.all.policy
        [ -r ${policy} ] || cat >${policy} <<'POLICY'
        grant codebase "file:${java.home}/../lib/tools.jar" {
        permission java.security.AllPermission;
        };
        POLICY
        
        jstatd -J-Djava.security.policy=${policy} -J-Djava.rmi.server.hostname=192.168.x.x &
        

        如果您想通过公共网络连接,则应将主机名分配为公共 ip。

        【讨论】:

          【解决方案9】:

          我创建了包含以下内容的新政策:

          授予代码库 "file:/usr/java/latest/lib/tools.jar" { 权限 java.security.AllPermission; };

          然后使用以下命令使用该策略启动 jstatd:

          jstatd -J-Djava.security.policy=/usr/java/jstatd.all.policy &

          【讨论】:

          • 使用 tools.jar 的硬编码路径而不是变量和相对路径效果很好
          【解决方案10】:

          除了 LightDye 的回答之外,您还可以使用以下命令在您的网络过滤器中打开所需的端口:

          for port in `netstat -nlp | grep jstatd | sed -r 's/^.*\:([0-9]{4,}).*$/\1/'`; do iptables -I INPUT 1 -p tcp --dport $port -j ACCEPT -m comment --comment jstatd; done
          

          【讨论】:

            【解决方案11】:

            或者您可以使用 ejstatd 代替 jstatd 自动处理此问题:只需在 ejstatd 文件夹中使用 mvn exec:java 运行它。

            免责声明:我是这个开源工具的作者。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-09-23
              • 2015-06-04
              • 1970-01-01
              • 2016-04-07
              • 2018-03-06
              • 1970-01-01
              • 2016-07-21
              • 2011-07-23
              相关资源
              最近更新 更多