Xinfeng Liu

http://developers.sun.com.cn/blog/lxf/date/20080912 星期五 九月 12, 2008

使用Sun Studio 和Solaris工具解决Java的性能问题

Sun Studio的performance analyzer是能同时对JVM和Java代码的profiling工具,而且比 起那些基于Java的Profiling工具要好用的多。使用Netbeans Profiler时候最好把项目工程放进Netbeans IDE里才好用,否则不方便对被profiling的应用做细粒度的profiling控制,导致大型应用被profiling后运行非常慢。而Sun Studio的performance analyzer对应用性能的影响要小得多,而且使用起来很简便。只要 collect -j on java <arguments> 就可以了。运行完后会生成一个结果数据目录比如test.1.er,然后用analyzer test.1.er 进行图形化的显示和分析,或使用er_print test.1.er进行命令行的显示。

Sun Studio performance analyzer对java profiling结果的分析,可以按三种模式显示: user, expert, machine。因此可以同时分析用户的Java代码和JVM的C++代码。如果你要分析JNI的代码,这个工具更是离不开了。下面是一个例子:

er_print test.1.er

(er_print) limit 20
(er_print) func
Functions sorted by metric: Exclusive User CPU Time

Excl.     Incl.      Name
User CPU  User CPU
   sec.      sec.
763.864   763.864    <Total>
218.053   218.053    <JVM-System>
 44.511    44.581    <Unknown>
 33.123    35.195    oracle.jdbc.driver.NumberCommonAccessor.getBigDecimal(int)
 21.145    52.287    oracle.jdbc.driver.ClobAccessor.getString(int)
 15.401    30.982    java.util.HashMap.get(java.lang.Object)
 14.630    20.364    sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(java.nio.CharBuffer, java.nio.ByteBuffer)
 13.209    13.259    oracle.jdbc.driver.OracleStatement.prepareAccessors()
 13.159    81.157    org.apache.jsp.home_jsp._jspService(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 12.429    15.271    oracle.jdbc.driver.T4C8TTIClob.read(byte[], long, long, boolean, char[])
 12.369    16.121    java.lang.String.regionMatches(boolean, int, java.lang.String, int, int)
 11.258    11.258    java.lang.String.equals(java.lang.Object)
 10.667    10.667    java.lang.Throwable.<init>()
  9.517     9.517    oracle.jdbc.driver.T4CConnection.createClobDBAccess()
  8.856    30.671    oracle.jdbc.driver.OracleStatement.getColumnIndex(java.lang.String)
  6.364     6.364    java.lang.String.indexOf(int, int)
  5.844    21.935    java.lang.String.equalsIgnoreCase(java.lang.String)
  5.674     5.674    java.nio.CharBuffer.arrayOffset()
  4.733     4.733    java.util.Arrays.copyOfRange(char[], int, int)
  4.703     4.703    oracle.net.ns.DataPacket.getDataFromBuffer(byte[], int, int)

(er_print) viewmode expert
(er_print) func
Functions sorted by metric: Exclusive User CPU Time

Excl.     Incl.      Name
User CPU  User CPU
   sec.      sec.
763.864   763.864    <Total>
 33.123    35.195    oracle.jdbc.driver.NumberCommonAccessor.getBigDecimal(int)
 21.145    52.287    oracle.jdbc.driver.ClobAccessor.getString(int)
 19.534    19.534    lwp_yield
 17.232    17.232    OopStarTaskQueueSet::peek()
 15.401    30.982    java.util.HashMap.get(java.lang.Object)
 14.630    20.364    sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(java.nio.CharBuffer, java.nio.ByteBuffer)
 13.980    21.855    PhaseChaitin::build_ifg_physical(ResourceArea*)
 13.209    13.259    oracle.jdbc.driver.OracleStatement.prepareAccessors()
 13.159    81.137    org.apache.jsp.home_jsp._jspService(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 13.129    13.289    IndexSetIterator::advance_and_next()
 12.429    15.271    oracle.jdbc.driver.T4C8TTIClob.read(byte[], long, long, boolean, char[])
 12.369    16.121    java.lang.String.regionMatches(boolean, int, java.lang.String, int, int)
 11.258    11.258    java.lang.String.equals(java.lang.Object)
 10.667    10.667    java.lang.Throwable.<init>()
  9.517     9.517    oracle.jdbc.driver.T4CConnection.createClobDBAccess()
  8.856    30.671    oracle.jdbc.driver.OracleStatement.getColumnIndex(java.lang.String)
  7.475     7.475    arrayof_oop_disjoint_arraycopy
  6.585     8.736    PhaseChaitin::Split(unsigned)
  6.364     6.364    java.lang.String.indexOf(int, int)

(er_print) viewmode machine
(er_print) func
Functions sorted by metric: Exclusive User CPU Time

Excl.     Incl.      Name
User CPU  User CPU
   sec.      sec.
763.864   763.864    <Total>
111.688   546.232    Interpreter
 57.850    60.702    typeArrayKlass::allocate(int,Thread*)
 20.324    20.394    sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(java.nio.CharBuffer, java.nio.ByteBuffer)
 19.534    19.534    lwp_yield
 17.232    17.232    OopStarTaskQueueSet::peek()
 16.291    16.291    java.lang.String.regionMatches(boolean, int, java.lang.String, int, int)
 14.850    31.062    oracle.jdbc.driver.OracleStatement.getColumnIndex(java.lang.String)
 13.980    21.855    PhaseChaitin::build_ifg_physical(ResourceArea*)
 13.129    13.289    IndexSetIterator::advance_and_next()
 11.638    11.638    java.lang.String.equals(java.lang.Object)
 11.588    15.000    java.lang.Object.hashCode()
  7.475     7.475    arrayof_oop_disjoint_arraycopy
  6.585     8.736    PhaseChaitin::Split(unsigned)
  6.545     6.545    java.lang.String.indexOf(int, int)
  5.754     5.754    jshort_disjoint_arraycopy
  5.484     5.484    flush_callers_register_windows
  5.324    16.742    java_lang_Throwable::fill_in_stack_trace(Handle,Thread*)
  5.284     5.284    memcpy
  5.014    18.333    java.util.Collections$SynchronizedMap.get(java.lang.Object)

有时,单单通过Java本身的工具(如jstat, jmap, jinfo, jconsole, java thread dump等)不足以分析出问题,还是需要依靠操作系统的工具来定位。比如pstack, prstat -mL -p <pid>,pmap -xs, DTrace等。假如通过prstat发现Java应用总是不能充分利用CPU,可以通过一个简单的DTrace脚本来找出原因:

offcpu.d
--------
#!/usr/sbin/dtrace -s
off-cpu
/pid == $target/
{
@[jstack(20,200)]=count();
}
tick-2sec
{
trunc(@,10);
printa(@);
clear(@);
}

# ./offcpu.d -p <java process id>

无论你愿不愿意承认,总之Java在Solaris上运行的最好,道理就不用说了。 


http://developers.sun.com.cn/blog/lxf/date/20080611 星期三 六月 11, 2008

Java的内存泄漏问题

 

 查找Java的内存泄漏一直是件困难的事情。一些基于instrument的工具无论是商业的还是开源的也都不是很有效,因为instrument对被测系统的影响太大,难以重现问题。尤其是对大型的应用以及生产系统上的调试帮助不大。

我一年多前写过一片这方面的文章,主要是讲Java内存泄漏常见的原因以及Java SE6提供的一些工具来帮助查找内存泄漏。但是临到发表时 ,我自己提出把它撤了下来,原因是觉得现有的这些工具还是不足够来百分之百地定位问题。现在想想还是把它以非正式的方式发出来比较好,希望能对人有所启发,下载。另外,netbeans的profiler现在应该有了长足的进步,只是自己没时间去研究,不知道有没有人能分享这方面的经验。

-xinfeng

http://developers.sun.com.cn/blog/lxf/date/20061001 星期日 十月 01, 2006

如何分析Java虚拟机死锁

我发现现在网上没有好好讲这个的,少数的几篇文章都是大谈自己的工具,却没把方法讲清楚。我决定以我以前碰到的case为例写一篇来分享。

到目前为止,我认为分析Java代码问题的最有效的工具仍然是java thread dump。

[Read More]

http://developers.sun.com.cn/blog/lxf/date/20060813 星期日 八月 13, 2006

如何让EJB客户端从Internet访问内网的Sun应用服务器

在Web2.0的时代提这东西实在有点过时,但它却是个困扰了我很久的问题,而且也确实有些用户要这样用。
[Read More]

http://developers.sun.com.cn/blog/lxf/date/20060606 星期二 六月 06, 2006

看看用jMaki 和 Netbean5.5 开发互动性的web应用有多简单!

使用了Ajax的控件。不多说了,看看demo吧。
https://ajax.dev.java.net/screencast/jMaki/jMaki.html

http://developers.sun.com.cn/blog/lxf/date/20060412 星期三 四月 12, 2006

通过软件实现Access Manager的负载均衡设置

还是以前写的文章,是英文的。http://developers.sun.com/prodtech/identserver/reference/techart/load-balancing.html

Access Manager的客户端证书认证

把以前写的文章整理一下。以后写东西先放到blog上供大家review。http://isv.sun.com.cn/techdocs/0601/index.jsp

http://developers.sun.com.cn/blog/lxf/date/20060405 星期三 四月 05, 2006

如何知道Java Class文件的Java版本

Java Class的版本信息位于class文件的头部。

-bash-3.00$ od -x Hello.class|more

输出大概象这样:
0000000 feca beba 0000 3100 2200 000a 0006 0914
.....

Look at 5th-8th bytes, this example is:
0000 3100
3100 is major version: 31 is jdk1.5, 30 is jdk1.4, 2F is jdk1.3...
0000 is minor version.

(Note: 1st-4th is Java magic number, it is always "cafebabe" :-))
You may find the version of some class files compiled by javac of jdk1.4 is '2e', it means the class file can be run by JDK1.2 or later, but it cannot be run by JDK1.1.

Thanks,
Xinfeng