分类 Java 相关 下的文章

Java heap dump OQL samples - where

where 可以包含:

=, <=, >, <, [ NOT ] LIKE, [ NOT ] IN, IMPLEMENTS (relational operations)
AND OR != , =
字段可以 [. ] . .

实现 group by 功能

  1. 方法1: 如果是 group by 其中一个字段 可以这样: 菜单选择 -> Java Basics -> Group by Values -> 给出类名和需要group by 的字段:
    group1.png group2.png
  2. 方法2: 使用 OQL. 举例: 假如我有很多 brave.handler.MutableSpan, 这个类有个实例字段是 name, 我想根据 name 去分组. 我们需要这么做:

    // 第0步, 我们查看我们要分组的对象
    SELECT toString(s.name), * FROM brave.handler.MutableSpan s
    
    // 第一步, 我们看看有多少唯一的 name
    SELECT DISTINCT toString(s.name) FROM brave.handler.MutableSpan s
    
    // 第二步, 做分组, 把上一步distinct的结果和原始列表对比, 第二列返回的每一行是一个list
    SELECT dn.name AS name, (SELECT OBJECTS lst FROM brave.handler.MutableSpan s WHERE (toString(s.name) = dn.name)) AS lst
    FROM 
    OBJECTS (SELECT DISTINCT toString(s.name) AS name FROM brave.handler.MutableSpan s) dn
    
    // 第三步, count 每个 group, 第二步第二列是一个list, 所以可以使用 .@length 来取长度
    SELECT g.name as name, g.lst.@length as size FROM OBJECTS ( eval((
    
    SELECT dn.name AS name, (SELECT OBJECTS s FROM brave.handler.MutableSpan s WHERE (toString(s.name) = dn.name)) AS lst
    FROM 
    OBJECTS (SELECT DISTINCT toString(s.name) AS name FROM brave.handler.MutableSpan s) dn
    
    )) ) g
  3. 使用上面第一步的结果, 然后导出到csv(菜单栏 -> 最右边-> 导出CSV), 然后excel 操作

查询 URL 相关的:

- SELECT * FROM java.net.URL u where u.port = 443
- SELECT * FROM java.net.URL u where toString(u.host) = "api.google.com"
- SELECT * FROM java.net.URL u where u.@displayName like ".*api.google.com.*"
- SELECT * FROM "com.tianxiaohui.*" u where toString(u) like ".*Metrics.*"  //正则
- SELECT s.address.holder.hostName.toString(), s.timeout FROM java.net.SocksSocketImpl s WHERE (s.port = 443) //socket 的地址和 timeout 时间
- SELECT toString(u.string) FROM java.net.URI u WHERE (toString(u.schemeSpecificPart) LIKE ".+google.com.+")

查询其它相关的:

- SELECT x.capacity FROM java.nio.DirectByteBuffer x WHERE ((toString(x.att) = "null") and (toString(x.cleaner) != "null") and (x.capacity >= (1024 * 1024)))
- SELECT DISTINCT objects x.this$0 FROM java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask x 
- SELECT distinct objects x FROM java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask x WHERE (x.this$0.toString() LIKE ".+0x468369b50")
- SELECT * FROM INSTANCEOF java.lang.Object t WHERE (toHex(t.@objectAddress) >= "0xfbd4c000" AND toHex(t.@objectAddress) <= "0xfce94050") //一段地址空间中的所有对象
- select * from java.nio.DirectByteBuffer x where x.capacity > 65535 and x.cleaner != null
- SELECT o.toString() FROM OBJECTS ( SELECT OBJECTS outbounds(t) FROM org.apache.tomcat.util.threads.TaskThread t WHERE (t.toString() = "DefaultThreadPool-23") ) o WHERE (o.toString() LIKE ".+TracingInfoImpl.+")

如果 0x789342b78 对应的地址是一个类class(不是instance), 那么可以用下面这种查法:
select * from 0x789342b78

如果要查询某个 Class 的 static 字段里面的数据:

SELECT * FROM java.lang.Class x where x.toString() LIKE ".+com.tianxiaohui.platform.config.impl.ConfigProvider.*"

如果要查询一个抽象类的具体实现:

select * from INSTANCEOF java.net.AbstractPlainSocketImpl

Java JDBC 相关的

# 一个连接有多少 open 的 ResultSet
SELECT * FROM oracle.jdbc.driver.OracleResultSetImpl rs WHERE (rs.connection.toString() LIKE ".+0x7a3af6cf8")

查看是不是包含某个关键字的字符串String:

SELECT * FROM java.lang.String s where s.toString() like ".*agepsvc.*"

查看栈桢信息

SELECT u.Thread AS Thread, u.Frame.@text AS Frame 
  FROM OBJECTS ( 
    SELECT t AS Thread, ${snapshot}.getThreadStack(t.@objectId).@stackFrames AS Frame 
      FROM java.lang.Thread t  ) u

过滤栈上面的局部变量:

SELECT vr.Thread, vr.Name, vr.Frame, vr.Local FROM OBJECTS ( 
    SELECT v.Thread AS Thread, toString(v.Thread) AS Name, v.Frame AS Frame, ${snapshot}.getObject(v.Objs) AS Local FROM OBJECTS ( 
        SELECT u.Thread AS Thread, u.Frame.@text AS Frame, u.Frame.@localObjectsIds AS Objs FROM OBJECTS ( 
            SELECT t AS Thread, ${snapshot}.getThreadStack(t.@objectId).@stackFrames AS Frame FROM INSTANCEOF java.lang.Thread t WHERE (toString(t.name) = "DefaultThreadPool-32") 
        ) u  
    ) v WHERE (v.Objs != null) 
) vr WHERE (vr.Local.toString() LIKE ".*TracingInfoImpl.*")

内置函数:

  1. toHex( number ) //转换数字为16进制
  2. toString( object ) //转换对象为 String
  3. dominators( object ) //被这个对象直接控制的
  4. dominatorof( object ) //这个对象被那些对象直接控制
  5. outbounds( object ) //
  6. inbounds( object ) //
  7. classof( object ) // 当前对象的类

如何查看一个对象的 dominator, 然后就可以用 dominatorof() 函数:

SELECT dominatorof(x) FROM OBJECTS 15038294 x 
SELECT * FROM org.ebayopensource.ginger.core.logging.impl.CalLogTransactionImpl x WHERE (dominatorof(x).toString() = "DefaultThreadPool-20")

dominator.png

更多OQL的官方文档参考: https://wiki.eclipse.org/MemoryAnalyzer/OQL

Java 常见的三种 dump 文件: Core Dump, heap dump, thread dump

  1. core dump: 有时又被称作 crash dump, memory dump, system dump, 它是某个进程在某个时间点的内存镜像. 它既可以在系统发生致命错误或无法处理的错误时候自动产生, 也可以通过命令工具产生. 但是 core dump 一遍并不能包含所有的内存页,但至少包含 heap 和 stack 的内存信息. core dump 默认放在当前进程的工作文件夹,并以core.pid 命名. 使用 jmap 转换 core dump 为 HPROF 文件(jmap -dump:format=b,file=dump.hprof /usr/bin/java core.1234) 或使用 Java VisualVM 来分析都可以. 也可以在 Linux 上面用 gdb --core core.1234 来分析.
  2. heap dump: 内存某个时间点镜像, 有ASCII 或 binary 格式,不同格式可能包含的信息不一样. 但一般包含 heap 里的类和对象实例信息. 但不包含什么时候或什么原因对象产生.
  3. thread dump: The thread dump consists of the thread stack, including thread state, for all Java threads in the virtual machine. The thread dump does not terminate the application: it continues after the thread information is printed.

如何使用 Java VisualVM 来分析 core dump
转换 core dump 为 HPROF 文件

_$jmap -dump:format=b,file=dump.hprof /usr/bin/java core.1234  //这个 java 是你 core dump 运行的 java
  • 如何产生 core dump
  • 如何产生 heap dump or 这里 or 这里
    -- 应用启动时: _$ java -agentlib:hprof=file=snapshot.hprof,format=b application
    -- 应用启动时: _$ java -XX:+HeapDumpOnOutOfMemoryError application
    -- _$ jcmd GC.heap_dump filename=Myheapdump
    -- _$ jmap -dump:format=b,file=snapshot.jmap pid
    -- 使用 JConsole 工具
  • 如何产生 thread dump
    -- _$ jstack -f 5824
    -- use VisualVM

JVM - jdb

jdb 是 Hotspot JDK 里面的一个命令行debug 实用工具。
实用 Java Debug Interface (JDI) 连接目标JVM。

JVM HPROF 笔记

HPROF 是一个 DDL 格式的工具, 用来做 JVM heap 和 CPU profiling 的,在每个 JDK 里面都有. 它把 profiling 信息要么写到文件, 要么以二进制或 ASCII 码格式写到 socket. 这些 profiling 工具可以被其它工具使用.

HPROF is a tool for heap and CPU profiling shipped with every JDK release. It is a dynamic-link library (DLL) that interfaces with the Java Virtual Machine (JVM) using the Java Virtual Machine Tool Interface (JVM TI). The tool writes profiling information either to a file or to a socket in ASCII or binary format. This information can be further processed by a profiler front end tool.

The HPROF tool is capable of presenting CPU usage, heap allocation statistics, and monitor contention profiles. In addition, it can report complete heap dumps and states of all the monitors and threads in the JVM. In terms of diagnosing problems, HPROF is useful when analyzing performance, lock contention, memory leaks, and other issues.

源代码在: $JAVA_HOME/demo/jvmti/hprof 目录
常用命令:

  1. java -agentlib:hprof=help
  2. java -agentlib:hprof ToBeProfiledClass
  3. java -agentlib:hprof=heap=sites ToBeProfiledClass
  4. java -agentlib:hprof=cpu=samples,interval=20,depth=3 classname
  5. java -agentlib:hprof=heap=sites classname

Option Name and Value Description Default


heap=dump|sites|all heap profiling all
cpu=samples|times|old CPU usage off
monitor=y|n monitor contention n
format=a|b text(txt) or binary output a
file= write data to file java.hprof[{.txt}]
net=: send data over a socket off
depth= stack trace depth 4
interval= sample interval in ms 10
cutoff= output cutoff point 0.0001
lineno=y|n line number in traces? y
thread=y|n thread in traces? n
doe=y|n dump on exit? y
msa=y|n Solaris micro state accounting n
force=y|n force output to y
verbose=y|n print messages about dumps y