65

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)
ryenus
  • 15,711
  • 5
  • 56
  • 63
michael nesterenko
  • 14,222
  • 25
  • 114
  • 182

12 Answers12

70

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} &
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
michael nesterenko
  • 14,222
  • 25
  • 114
  • 182
  • @michael nesterenko , Cannot connect to XXXXXXXX:8091 using service:jmx:rmi:///jndi/rmi://XXXXXX:8091/jmxrmi I am getting this error, what might be wrong ? – Jet Jan 30 '18 at 07:25
  • Hi, Michael. Your solution is working well for me - I only changed the path to the policy file to be a hard-coded path because of what I've read in some other posts. I was wondering how I can stop jstatd when it is run in the background with the &. I've tried ps -x to see if I see the process but I don't, even though it is running because Visual VM can connect to it. Please let me know if you have any idea on how I can kill the process when I'm done with it. – Erich Mar 07 '19 at 22:25
  • D'oh! I started the processes as root, so I needed to do "sudo su" in order for the process to appear in the list. – Erich Mar 08 '19 at 22:31
66

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.

LightDye
  • 1,234
  • 11
  • 15
  • 8
    In my case some how ${java.home} or ${JAVA_HOME} did not work. I had to specify the full absolute path of tools.jar. – suman j Apr 23 '14 at 19:17
  • 2
    I had to use absolute paths both in the policy file and in the shell command. – jrharshath Aug 22 '14 at 18:54
  • @lisak, sorry I put the -J that you removed back in the parameter `-J-Djava.security.policy=/absolute-path-to/jstatd.all.policy` because that is how is meant to be according to [jstatd documentation from Oracle](http://docs.oracle.com/javase/7/docs/technotes/tools/share/jstatd.html). Have you found an environment or jstatd version where that isn't the case? – LightDye Apr 09 '15 at 02:43
  • Imho it is no longer supported in java 1.8, at least it didn't work for me and from what I remember it works without `-J` even on java 1.7 ... – lisak Apr 09 '15 at 08:36
  • I tried without `-J` in Java 1.7 on Windows 7 and it doesn't seem to work. I have successfully used the `-J` on Java 1.5 and 1.6 on Solaris 5.10. If it is no longer supported in Java 1.8, maybe we should just add a note, but keeping the `-J` as it might be required in other versions or platforms. – LightDye Apr 09 '15 at 13:56
  • Everything worked when I added `-J-Djava.rmi.server.hostname=my_server_ip`. So at the end it was `jstatd -p 12345 -Djava.security.policy=/absolute-path-to/jstatd.all.policy -J-Djava.rmi.server.hostname=my_server_ip` – Francisco López-Sancho Jun 10 '15 at 10:52
  • "Using VisualVM to monitor a remote JBoss instance" appears to be a dead link. – jwv Aug 10 '15 at 14:22
  • jstatd.all.policy file needs to be created at ${JAVA_HOME}/bin dir. I had to specify absolute path for it. Now simply run '${JAVA_HOME}/bin/jstatd -J-Djava.security.policy=/absolute/path/to/jstatd.all.policy &' verify with 'netstat -nap | grep jstatd' – Rishi Sep 18 '15 at 18:36
  • Step 4 made me double-check my path - I was getting `Could not create remote object access denied ("java.util.PropertyPermission" "java.rmi.server.ignoreSubClasses" "write")` simply because the path I had specified to my policy file was incorrect. Check yours! – roj Jan 03 '18 at 01:20
  • @LightDye , Cannot connect to XXXXXXXX:8091 using service:jmx:rmi:///jndi/rmi://XXXXXX:8091/jmxrmi I am getting this error, what might be wrong ? – Jet Jan 30 '18 at 07:26
20

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.

ryenus
  • 15,711
  • 5
  • 56
  • 63
  • Worth noting that the `lib` directory is located directly under the JDK root, so the path probably shouldn't have the `..`. I used `file:${JAVA_HOME}/lib/tools.jar`. – nbrooks May 15 '19 at 22:22
3

if you are using Java 11, you need view this answer:Starting jstatd in Java 9+ - Stack Overflow
policy file is like this:

grant codebase "jrt:/jdk.jstatd" {    
   permission java.security.AllPermission;    
};
peter zhang
  • 1,247
  • 1
  • 10
  • 19
2

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.

Vadim
  • 5,154
  • 2
  • 20
  • 18
2

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
tster
  • 17,883
  • 5
  • 53
  • 72
  • I don't think there is a need to put it in /tmp, just make sure the filename is correct. I accidentally named mine jstatd.policy.all which didn't match. – David I. Oct 01 '14 at 16:56
2

Just an additional point about previous answers that cost me some minor time to figure out.
When I used relative path in the policy file ${java.home}/lib/tools.jar it actually pointed jstatd to JAVA_HOME/jre/ directory and since I had jdk installed I had to use ${java.home}/../lib/tools.jar instead to get to the right place.

EDIT I was running jstatd from within a docker container running ubuntu with jdk 8 (JAVA_HOME was set correctly).

1

@michael nesterenko 's answer is all right.

But if sometimes you can't connect the server even if you have get the Jstatd up, u may try to assign the '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 &

the hostname shoule be assigned as the public ip if you want to connect via public network.

Dai Kaixian
  • 1,045
  • 2
  • 14
  • 24
1

I created new policy with following content:

grant codebase "file:/usr/java/latest/lib/tools.jar" { permission java.security.AllPermission; };

and then start jstatd with that policy with following command:

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

Nitin Taur
  • 11
  • 4
0

in addition to LightDye's answer, you can open required ports in your netfilter with this command :

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
PHaroZ
  • 23
  • 1
  • 4
0

Or you can use ejstatd instead of jstatd which automatically handles this problem: just run it using mvn exec:java inside ejstatd folder.

Disclaimer: I'm the author of this open source tool.

Anthony O.
  • 22,041
  • 18
  • 107
  • 163
0
    grant codebase "jrt:/jdk.jstatd" {    
       permission java.security.AllPermission;    
    };
    grant codebase "jrt:/jdk.internal.jvmstat" {    
       permission java.security.AllPermission;    
    };

Try adding the above to

"C:\Program Files\Java\jdk-18.0.2.1\lib\security{policyFile}"

Ticherhaz FreePalestine
  • 2,738
  • 4
  • 20
  • 46