Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An Serviceability-Agent based tool to see stats of NIO direct memory, as an alternative on JDK6 without JMX support for direct memory monitoring. Only works on JDK6; to work on JDK7 will need some tweaking because static variables are moved to Java mirror
$ java -version
java version "1.6.0_30"
Java(TM) SE Runtime Environment (build 1.6.0_30-b12)
Java HotSpot(TM) 64-Bit Server VM (build 20.5-b03, mixed mode)
$ javac -classpath $JAVA_HOME/lib/sa-jdi.jar DirectMemorySize.java
$ jps
18486 GroovyStarter
23135 Jps
$ java -classpath .:$JAVA_HOME/lib/sa-jdi.jar DirectMemorySize `pgrep java`
Attaching to process ID 18486, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.5-b03
NIO direct memory: (in bytes)
reserved size = 0.000000 MB (0 bytes)
max size = 4069.000000 MB (4266655744 bytes)
[sajia@211 temp]$ java -cp .:$JAVA_HOME/lib/sa-jdi.jar DirectMemorySize
Usage: java directMemorySize [option] <pid>
(to connect to a live java process)
or java directMemorySize [option] <executable> <core>
(to connect to a core file)
or java directMemorySize [option] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server)
where option must be one of:
-e to print the actual size malloc'd
-v to print verbose info of every live DirectByteBuffer allocated from Java
-h | -help to print this help message
[sajia@211 temp]$ java -cp .:$JAVA_HOME/lib/sa-jdi.jar DirectMemorySize `pgrep -u sajia java`
Attaching to process ID 7381, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.5-b03
NIO direct memory: (in bytes)
reserved size = 0.000003 MB (3 bytes)
max size = 7152.000000 MB (7499415552 bytes)
[sajia@211 temp]$ java -cp .:$JAVA_HOME/lib/sa-jdi.jar DirectMemorySize -e `pgrep -u sajia java`
Attaching to process ID 7381, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.5-b03
NIO direct memory: (in bytes)
reserved size = 0.000003 MB (3 bytes)
max size = 7152.000000 MB (7499415552 bytes)
Finding object size using Printezis bits and skipping over...
Finding object size using Printezis bits and skipping over...
NIO direct memory malloc'd size: 0.007815 MB (8195 bytes)
[sajia@211 temp]$ time java -cp .:$JAVA_HOME/lib/sa-jdi.jar DirectMemorySize `pgrep -u sajia java`
Attaching to process ID 7381, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.5-b03
NIO direct memory: (in bytes)
reserved size = 0.000003 MB (3 bytes)
max size = 7152.000000 MB (7499415552 bytes)
real 0m0.401s
user 0m0.503s
sys 0m0.057s
[sajia@211 temp]$ time java -cp .:$JAVA_HOME/lib/sa-jdi.jar DirectMemorySize -e `pgrep -u sajia java`
Attaching to process ID 7381, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.5-b03
NIO direct memory: (in bytes)
reserved size = 0.000003 MB (3 bytes)
max size = 7152.000000 MB (7499415552 bytes)
Finding object size using Printezis bits and skipping over...
Finding object size using Printezis bits and skipping over...
NIO direct memory malloc'd size: 0.007815 MB (8195 bytes)
real 0m4.822s
user 0m2.095s
sys 0m3.216s
[sajia@211 temp]$ time java -cp .:$JAVA_HOME/lib/sa-jdi.jar DirectMemorySize -e -v `pgrep -u sajia java`
Attaching to process ID 7381, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.5-b03
NIO direct memory: (in bytes)
reserved size = 0.000003 MB (3 bytes)
max size = 7152.000000 MB (7499415552 bytes)
Currently allocated direct buffers:
0x00002aaab021df10: capacity = 0.000001 MB (1 bytes), mallocSize = 0.003907 MB (4097 bytes)
0x00002aaab0843310: capacity = 0.000002 MB (2 bytes), mallocSize = 0.003908 MB (4098 bytes)
Finding object size using Printezis bits and skipping over...
Finding object size using Printezis bits and skipping over...
NIO direct memory malloc'd size: 0.007815 MB (8195 bytes)
real 0m5.097s
user 0m2.164s
sys 0m3.426s
[sajia@211 temp]$
[sajia@xxx164 gist]$ sudo -u admin java -cp .:$JAVA_HOME/lib/sa-jdi.jar DirectMemorySize -e `pgrep -u admin java` | grep -v 'Finding object'
Attaching to process ID 2499, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.0-b12-internal
NIO direct memory: (in bytes)
reserved size = 907.541405 MB (951626136 bytes)
max size = 3925.375000 MB (4116054016 bytes)
NIO direct memory malloc'd size: 910.697655 MB (954935704 bytes)
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.tools.*;
import sun.jvm.hotspot.utilities.*;
public class DirectMemorySize extends Tool {
private boolean exactMallocMode;
private boolean verbose;
public DirectMemorySize(boolean exactMallocMode, boolean verbose) {
this.exactMallocMode = exactMallocMode;
this.verbose = verbose;
}
public void run() {
// Ready to go with the database...
try {
long reservedMemory = getStaticLongFieldValue("java.nio.Bits", "reservedMemory");
long directMemory = getStaticLongFieldValue("sun.misc.VM", "directMemory");
System.out.println("NIO direct memory: (in bytes)");
System.out.printf(" reserved size = %f MB (%d bytes)\n", toM(reservedMemory), reservedMemory);
System.out.printf(" max size = %f MB (%d bytes)\n", toM(directMemory), directMemory);
if (verbose) {
System.out.println("Currently allocated direct buffers:");
}
if (exactMallocMode || verbose) {
final long pageSize = getStaticIntFieldValue("java.nio.Bits", "pageSize");
ObjectHeap heap = VM.getVM().getObjectHeap();
InstanceKlass deallocatorKlass =
SystemDictionaryHelper.findInstanceKlass("java.nio.DirectByteBuffer$Deallocator");
final LongField addressField = (LongField) deallocatorKlass.findField("address", "J");
final IntField capacityField = (IntField) deallocatorKlass.findField("capacity", "I");
final int[] countHolder = new int[1];
heap.iterateObjectsOfKlass(new DefaultHeapVisitor() {
public boolean doObj(Oop oop) {
long address = addressField.getValue(oop);
if (address == 0) return false; // this deallocator has already been run
long capacity = capacityField.getValue(oop);
long mallocSize = capacity + pageSize;
countHolder[0]++;
if (verbose) {
System.out.printf(" 0x%016x: capacity = %f MB (%d bytes),"
+ " mallocSize = %f MB (%d bytes)\n",
address, toM(capacity), capacity,
toM(mallocSize), mallocSize);
}
return false;
}
}, deallocatorKlass, false);
if (exactMallocMode) {
long totalMallocSize = reservedMemory + pageSize * countHolder[0];
System.out.printf("NIO direct memory malloc'd size: %f MB (%d bytes)\n",
toM(totalMallocSize), totalMallocSize);
}
}
} catch (AddressException e) {
System.err.println("Error accessing address 0x"
+ Long.toHexString(e.getAddress()));
e.printStackTrace();
}
}
public static long getStaticLongFieldValue(String className, String fieldName) {
InstanceKlass klass = SystemDictionaryHelper.findInstanceKlass(className);
LongField field = (LongField) klass.findField(fieldName, "J");
return field.getValue(klass); // on JDK7 use: field.getValue(klass.getJavaMirror());
}
public static int getStaticIntFieldValue(String className, String fieldName) {
InstanceKlass klass = SystemDictionaryHelper.findInstanceKlass(className);
IntField field = (IntField) klass.findField(fieldName, "I");
return field.getValue(klass); // on JDK7 use: field.getValue(klass.getJavaMirror());
}
public static double toM(long value) {
return value / (1024 * 1024.0);
}
public String getName() {
return "directMemorySize";
}
protected void printFlagsUsage() {
System.out.println(" -e\tto print the actual size malloc'd");
System.out.println(" -v\tto print verbose info of every live DirectByteBuffer allocated from Java");
super.printFlagsUsage();
}
public static void main(String[] args) {
boolean exactMallocMode = false;
boolean verbose = false;
// argument processing logic copied from sun.jvm.hotspot.tools.JStack
int used = 0;
for (String arg : args) {
if ("-e".equals(arg)) {
exactMallocMode = true;
used++;
} else if ("-v".equals(arg)) {
verbose = true;
used++;
}
}
if (used != 0) {
args = Arrays.copyOfRange(args, used, args.length);
}
DirectMemorySize tool = new DirectMemorySize(exactMallocMode, verbose);
tool.start(args);
tool.stop();
}
}

Also works on core dumps, in the form of:

java -cp .:$JAVA_HOME/lib/sa-jdi.jar DirectMemorySize $JAVA_HOME/bin/java core.xxx
@asafm

This comment has been minimized.

Show comment
Hide comment
@asafm

asafm Aug 1, 2013

irectMemorySize.java:3: package sun.jvm.hotspot.memory does not exist
import sun.jvm.hotspot.memory.*;
^

Couldn't find this package from some reason. Running on Mac OSX

asafm commented Aug 1, 2013

irectMemorySize.java:3: package sun.jvm.hotspot.memory does not exist
import sun.jvm.hotspot.memory.*;
^

Couldn't find this package from some reason. Running on Mac OSX

@caoxudong

This comment has been minimized.

Show comment
Hide comment
@caoxudong

caoxudong Aug 7, 2013

@asafm

Package "sun.jvm.hotspot.memory.*" is in the $JAVA_HOME/lib/sa-jdi.jar. Did you add this jar to CLASSPATH?

@asafm

Package "sun.jvm.hotspot.memory.*" is in the $JAVA_HOME/lib/sa-jdi.jar. Did you add this jar to CLASSPATH?

@fuyou001

This comment has been minimized.

Show comment
Hide comment

收藏了

@JinhouLiu

This comment has been minimized.

Show comment
Hide comment

学习

@allwmh

This comment has been minimized.

Show comment
Hide comment
@allwmh

allwmh Oct 28, 2014

HI 我执行完一次之后。kill -9 DirectMemorySize 的运行进城后,想再次使用就一直连接不上去 。这是为什么呢?

allwmh commented Oct 28, 2014

HI 我执行完一次之后。kill -9 DirectMemorySize 的运行进城后,想再次使用就一直连接不上去 。这是为什么呢?

@yikebocai

This comment has been minimized.

Show comment
Hide comment
@yikebocai

yikebocai Nov 14, 2014

使用-e-v参数时只显示和不加参数时同样的信息,上面例子上给出的额外信息一直长时间无法显示,是什么原因?

[root@cass047202 ~]# java -classpath .:/usr/install/java/lib/sa-jdi.jar DirectMemorySize -e 2904
Attaching to process ID 2904, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.51-b03
NIO direct memory: (in bytes)
  reserved size = 32686.010643 MB (34273766296 bytes)
  max size      = 27566.686493 MB (28905765856 bytes)

使用环境 CentOS 6.5 64bit,物理内存32G,Jdk7,Xmx8G

还有一个问题,按你这篇文章http://hllvm.group.iteye.com/group/topic/27945 提到的,如果参数 -XX:MaxDirectMemorySize没有设置,默认应该是约等了-Xmx8g这个值,为何这里显示是将近27G?

使用-e-v参数时只显示和不加参数时同样的信息,上面例子上给出的额外信息一直长时间无法显示,是什么原因?

[root@cass047202 ~]# java -classpath .:/usr/install/java/lib/sa-jdi.jar DirectMemorySize -e 2904
Attaching to process ID 2904, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.51-b03
NIO direct memory: (in bytes)
  reserved size = 32686.010643 MB (34273766296 bytes)
  max size      = 27566.686493 MB (28905765856 bytes)

使用环境 CentOS 6.5 64bit,物理内存32G,Jdk7,Xmx8G

还有一个问题,按你这篇文章http://hllvm.group.iteye.com/group/topic/27945 提到的,如果参数 -XX:MaxDirectMemorySize没有设置,默认应该是约等了-Xmx8g这个值,为何这里显示是将近27G?

@simmel

This comment has been minimized.

Show comment
Hide comment
@simmel

simmel Jan 15, 2015

Any love to port this to JDK8?

simmel commented Jan 15, 2015

Any love to port this to JDK8?

@reza987

This comment has been minimized.

Show comment
Hide comment

reza987 commented Dec 19, 2017

21124143_1044357149040746_2070796490_n
55666

@reza987

This comment has been minimized.

Show comment
Hide comment
@reza987

reza987 Dec 19, 2017

he is addicted for yaba for long time he always motivated new one comer.

reza987 commented Dec 19, 2017

he is addicted for yaba for long time he always motivated new one comer.

@ydx2008

This comment has been minimized.

Show comment
Hide comment
@ydx2008

ydx2008 Mar 5, 2018

can it works on java8?

ydx2008 commented Mar 5, 2018

can it works on java8?

@Rayn-liuwei

This comment has been minimized.

Show comment
Hide comment
@Rayn-liuwei

Rayn-liuwei Mar 8, 2018

tool.run(args) modify to tool.execute(args);

tool.run(args) modify to tool.execute(args);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment