cannot start jstatd due to permission error

I try to run jstatd jvm monitoring tool on linux machine

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

with following command:

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

jstatd.all.policy contents

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

   permission java.security.AllPermission;

};

Unfortunately I get following output:

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)

For some reason jstatd runs successfully on windows with the same command and policy file.

Linux java version:

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 version:

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)

Just found following script to run jstatd. I managed to run jstatd with this script 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} &

This is what worked for me:

  1. Make sure that tools.jar file exists and the user running the jstatd command has permissions to read it.

  2. Make sure that the URL in the jstatd.all.policy that points to the tools.jar is correct and declares the protocol (file in this case). For example, depending on where the java.home variable points to, you may need to remove the ../ part in the path just like this (I had to):

    grant codebase "file:${java.home}/lib/tools.jar" {
       permission java.security.AllPermission;
    };
    
  3. Starting from Java 1.4 the policy file needs to be encoded in UTF-8 without BOM. The EOL (CRLF vs LF) shouldn't really matter. Please see "Default Policy Implementation and Policy File Syntax" document from Oracle, under "Changes" section for more information (link not provided because I don't have enough reputation points to post more than 2 links, but I'm sure you'll be able to find that document).

  4. Use an absolute path to the policy file when running the jstatd command, e.g.

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

    EDIT: The -J parameter may no longer be required or supported in Java 1.8 so this command would be instead:

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

    (thanks @lisak for pointing this out)

  5. Finally, once you pass this point you may find other problems (I did) and these posts pointed me in the right direction: Using VisualVM to monitor a remote JBoss instance and Remote Profiling of JBoss using VisualVM. Basically you may need to use the -p parameter to use a different port if 1099 is already in use and add some java options in the JBoss run.conf via JAVA_OPTS (assuming you are monitoring JBoss instance). All explained in more detail in the links provided.

EDIT: - Pointed dead link Using VisualVM to monitor a remote JBoss instance to another page with the same content.


A one liner using process substitution (though bashism):

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

Wrapped:

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

As of jdk1.8.0_92, the java launcher option prefix -J is still required.

Note:

The original problem is more likely due to the tilde ~, in ~/jstatd.all.policy, isn't expanded hence not understood by java, meanwhile either absolute path or using ${HOME} instead should work.


I have the same problem and that what you should do:

  1. Make sure that javac is in your $PATH
  2. Specify full (absolute) path to the policy file when running jstatd
    jstatd -J-Djava.security.policy=/path/to/jstatd.all.policy

It helped for me.


Are you specifying your path wrong (i was)?

Try putting the policy in /tmp/jstatd.all.policy and then running:

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