热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

JRockit提高LinuxJava性能的分析

文章标题:JRockit提高LinuxJava性能的分析。Linux是中国IT实验室的一个技术频道。包含桌面应用,Linux系统管理,内核研究,嵌入式系统和开源等一些基本分类

  通过分析Java线程堆解决Java应用程序中存在问题的技术。我们可以使用线程堆来分析诸如应用程序挂起,响应时间长以及程序崩溃等情况。在详细介绍分析线程堆的技术之前,我们先来简要地看看线程堆本身。
  
  Java线程堆是一个运行中的Java应用程序的所有线程的一个快照。它会显示一些像当前的堆栈跟踪、状态以及线程名称之类的信息。线程列表中包括由JVM本身创建的线程(负责垃圾收集、信号处理等管理工作)和由应用程序创建的线程。
  
  通过给JVM发送一个SIGQUIT信号,您可以得到一个线程堆。在Unix操作系统(Solaris/Linux/HP-Unix等)中,通过kill-3命令可以得到线程堆。输出出线程堆之后,应用程序继续正常运行。当您给JVM发送SIGQUIT信号时,JVM的信号处理器会通过输出线程堆来响应这一信号。当程序运行的时候,您可以在任何点得到线程堆。
  
  线程堆的一个例子
  清单1显示的就是一个使用Sun JVM 1.4.1的单线程应用程序中的线程堆的例子。main线程是主应用程序线程。所有其他的线程都是由JVM创建的,负责完成一些管理工作。当分析应用程序级的问题时,我们通常只关心应用程序线程。下面,我们来分析清单1中main线程的堆栈跟踪。
  
  "main" prio=5 tid=0x002358B8 nid=0x7f8 runnable [6f000..6fc40]
  at test.method1(test.java:10)
  at test.main(test.java:5)
  
  从这个代码片断中您可以看到,一个线程堆栈跟踪有一个名称、线程优先级(prio=5)、状态(可运行的)、源代码行号,以及方法调用。从这个堆栈跟踪中可以得到如下结论:main线程执行test类的method1方法中的一些代码。而对method1方法的调用是由同一个类的main方法完成的。您也可以看到那些方法中确切的源代码行号。
  
  在从一些更复杂的情况去分析线程堆之前,我们先来讨论那些可以在线程堆中看到的线程的不同状态以及它们的意义。
  
  · 可运行的:当获得CPU的使用权时就可以运行或准备好运行的状态。JRockit线程堆把这种状态称为ACTIVE。
  
  · 在监视中等待:指在一个对象上休眠或等待上述时间,或者等待另一个线程的通知。这种情况会出现在对Thread对象调用任何sleep() 方法或者对Object调用wait() 方法时。
  
  例如,在BEA WebLogic Server中,空闲的执行线程就处于这种状态,它们会等待一个socket阅读器线程通知它们去做一些新的工作。堆栈跟踪如下所示:
  
  "ExecuteThread: '2' for queue: 'weblogic.admin.RMI'"daemon prio=5 tid=0x1752F040 nid=0x180c in Object.wait()[1887f000..1887fd8c]at java.lang.Object.wait(Native Method)waiting on (a weblogic.kernel.ExecuteThread)at java.lang.Object.wait(Object.java:426)
  
  JVM的其他版本把这种状态称为CW。JRockit将这种状态称为WAITING。
  
  · 等待监视实体:等待锁住一个对象(其他线程目前正控制着锁)。如果两个或者多个线程都想在同一时刻执行一个对象的某些同步代码块或方法,就会出现这种情况。请注意,锁总是加在一个对象上而不是加在独立的方法上。也就是说,如果一个线程要执行一个对象的同步方法,它必须先给那个对象加锁。
  
  下面显示的就是这种情况下的一个线程的堆栈跟踪的例子:
  
  "ExecuteThread: '24' for queue: 'DisplayExecuteQueue'" daemon prio=5tid=0x5541b0 nid=0x3b waiting for monitor entry [49b7f000..49b7fc24]at weblogic.cluster.replication.ReplicationManager.createSecondary(ReplicationManager.java:908)- waiting to lock (a java.lang.Object)at weblogic.cluster.replication.ReplicationManager.updateSecondary(ReplicationManager.java:715)
  在上述代码片断中,您们可以看到这个线程已经锁住了一个对象(6c408700),并且还在等待锁住另一个对象(6c4b9130)。
  
  JVM的其他版本可能不会在堆栈跟踪中给出对象ID的加锁信息。这种情况下,我们可以从线程的状态中推测出线程正在等待给对象加锁。同样的状态也许会被称为MW。JRockit将这种状态称为LOCKED。
  
  现在,我们来看看各种不同情况下的一些线程堆,并通过分析它们来寻找应用程序中的问题。
  
  死锁应用程序中的线程堆
  在清单2(只显示了部分线程堆)中,您可以看到JVM已经发现了死锁并且在线程堆中给出了该信息。消息中很清楚地表明了“ExecuteThread: '47' for queue: 'default'”正在等待给被"ExecuteThread: '57' for queue: 'default'"锁住的对象加锁。(这个线程堆来自于WebLogic Server。这些线程都是WebLogic Server的工作线程,它们负责处理客户机请求。)同时,执行线程47也锁住了执行线程57正在等待加锁的一个对象。这就是死锁。在这种状态下,这两个线程都无法继续运行,它们都在等待另一个线程释放锁。
  
  在清单2中,执行线程1正在等待给ConnectionScavanger对象加锁,但是这个对象目前已经被线程47锁住了,正如前面提到过的,线程47又被线程57死锁了。因此,执行线程1也无法继续运行下去。这最终将导致程序的挂起,因为服务器中的其他执行线程随后也会试图获得那个被执行线程47和57锁住的对象的锁。
  
  有些JVM不会给出死锁信息。它只会给出线程堆。这时候,我们可以通过查看线程的状态和堆栈跟踪得出同样的结论。
  
  上述这个情况中的问题源于WebLogic中的一个bug,后来已经修复了。
  
  其他挂起的情况
  在一些情况下,您可能会看到大多数线程都是“可运行”的,但是服务器仍然会挂起,无法响应客户机的请求。如果某些线程在做IO(输入输出)操作,它们可能会在执行read()方法的时候被阻塞住,但是状态还是“可运行的”(数据库或其他网络响应的情况可能很糟)。如果出现这种情况,您需要检查数据库和网络是否正常。
  
  一个“可运行的”线程被阻塞住还可能是由下列原因引起的:
  
  · 程序代码中的无限循环。这会导致严重的CPU占用。
  
  · JVM的垃圾收集可能会运行很长时间,占据大量的CPU时间。
  
  · JVM进程可能会用完文件描述符。
  
  如果应用程序的代码调用了wait()方法或sleep()方法,线程在休眠时间内不会继续运行——这时线程的状态就是“在监视中等待”。出现这种情况,应该检查程序代码。
  
  对一个对象的争用也会引起系统性能的下降,最终会导致出现类似于挂起的状态。这种情况下,大多数线程的状态就是“等待监视实体”。所以应该仔细检查程序代码以减少对特定对象的争用。线程可能在等待来自另一个服务器的响应,而另一个服务器可能由于其他原因也处于挂起状态,它就无法给这个服务器发送响应信息。
  
  在上述所有情况中,您都需要每隔几秒取一个线程堆(总共取多个线程堆),从而能够比较所有线程堆中的某一个线程的状态,并且您可以决定线程可以继续运行还是继续等待。
  
  JVM崩溃的情况
  JVM的崩溃可能会由下列原因引起:
  
  1.JVM库中的bug。
  
  2.应用程序错误地使用了JNI API。
  
  3.应用程序(原生数据库驱动等)所用的原生模块中存在bug。
  
  通常,当JVM崩溃的时候,它会给出引起崩溃的Java线程的堆栈跟踪。一些JVM会在退出之前给出一个完整的线程堆(所有线程的堆栈跟踪)。我们关心这些线程堆的目的主要在于寻找崩溃时正在运行的是哪个线程。这个线程称为“当前线程”。如果JVM给出一个完整的线程堆,它会标出“当前线程”。因此,一般来说找出引起崩溃的线程还是比较容易的。
  
  注意,崩溃的线程堆通常输出到stdout或stderr。JVM可能也会生成一个二进制格式的核心文件。
  
  崩溃线程堆的例子
  如果您检查一下清单3中的崩溃线程堆,您可以看到引起崩溃的线程的堆栈跟踪如下所示:
  
  Current Java thread:
  at com.aaa.bbb.qqq.Direct.setString(Native Method)
  at com.aaa.bbb.qqq.PreparedStatement.setString(PreparedStatement.java:51)
  - locked (a com.aaa.bbb.qqq.PreparedStatement)
  最后一个执行的方法(setString)是类“com.aaa.bbb.qqq.Direct”中的一个“原生方法”。因此,我们可以推测出崩溃正是由setString方法的实现中的原生代码引起的。崩溃的原因也可以归结为实现JNI API的JVM库代码有问题。
  
  您还可以看到JVM在堆中给出了下面的信息:
  
  Unexpected Signal : 11 occurred at PC=0x403AC9D1
  Function=(null)+0x403AC9D1
  Library=/opt/sunjdk/1.4.1_01-b01/jre/lib/i386/client/libjvm.so
  # HotSpot Virtual Machine Error : 11
  # Error ID : 4F530E43505002E6
  # Please report this error at
  # http://java.sun.com/cgi-bin/bugreport.cgi
  这意味着引起崩溃(PC=0x403AC9D1)的代码是JVM库的一部分:"/opt/sunjdk/1.4.1_01-b01/jre/lib/i386/client/libjvm.so"。但这并不表示JVM一定有bug。尽管引起崩溃的指示是在JVM代码中,但崩溃也可能是由于应用程序代码(这里是指原生方法setString的实现)的JNI调用引起的,应用程序代码可能传递了一些错误的变量,从而导致JVM模块的崩溃。
  
  如果在堆中没有“当前线程”的信息,那么我们就需要分析核心堆。这一内容不在本文的讨论范围之中。
推荐阅读
  • 本文详细介绍了在PHP中如何创建新文件以及如何使自定义函数在整个项目中全局可用的方法,包括最新的实践技巧。 ... [详细]
  • Windows 平台 Ruby on Rails 安装指南
    本文详细介绍如何在 Windows 系统上安装 Ruby 及其开发框架 Rails,包括必要的环境配置和组件安装。 ... [详细]
  • 本文介绍了一种解决方案,当笔记本电脑不具备作为无线接入点的能力时,如何通过开启Android手机的便携WLAN热点功能,使笔记本能够连接到手机并共享其网络资源,从而实现上网。文中详细描述了在Linux系统下配置的具体步骤。 ... [详细]
  • 本文介绍了在一卡通项目中设计加密管理方案时,证书服务器的配置步骤及其在用户权限控制中的应用。首先概述了证书服务器的基本设置,包括操作系统的选择和证书服务的安装,随后详细描述了服务器证书及客户端证书的创建过程。 ... [详细]
  • 面试技巧:如何清晰解释TCP的三次握手与四次挥手
    在技术面试中,正确且深入地解释TCP连接的建立与断开过程是非常重要的。本文不仅提供了对三次握手和四次挥手的基本理解,还深入探讨了这些过程中涉及的关键点,帮助面试者更加专业地回答相关问题。 ... [详细]
  • 本文详细解析了在Oracle数据库操作中遇到的ORA-01846错误,该错误通常出现在尝试使用NEXT_DAY函数处理日期时,因客户端和服务器端字符集不匹配导致的问题。文章不仅提供了错误的具体表现,还深入分析了错误原因,并给出了多种解决方案。 ... [详细]
  • 在网络通信领域,了解不同数制间的转换对于解析IP地址至关重要。本文将深入探讨IPv4和IPv6地址的不同表示方式,以及如何在这三种数制——二进制、十进制和十六进制之间进行有效的转换。 ... [详细]
  • 解决phpMyAdmin运行错误:mysqli_init(): 属性访问尚未允许
    本文探讨了在使用phpMyAdmin过程中遇到的mysqli_init()函数错误,并提供了有效的解决方案。 ... [详细]
  • 本文探讨了在执行SQL查询时遇到的因字符集不同而导致查询结果差异的问题,特别是涉及中文字符时。文章分析了在不同字符集设置下,SQL查询结果的变化,并提供了详细的解决方案。 ... [详细]
  • 在尝试使用sp_rename对名为'账号表'的表进行重命名操作时,遇到错误15051,提示无法重命名表,因为该表已被设置为复制发布。本文将探讨这一问题的原因及解决方案。 ... [详细]
  • 探讨在数据库中存储URL时,删除尾部斜杠的安全性和潜在影响,以及如何确保URL的一致性。 ... [详细]
  • 本文探讨了如何在JavaScript中调用PHP函数及实现两者之间的有效交互,包括通过AJAX请求、动态生成JavaScript代码等方法。 ... [详细]
  • 本文详细介绍了如何通过电脑上的网络设置来更改域名的DNS服务器地址,帮助用户更好地管理和优化网络访问。 ... [详细]
  • 本文详细探讨了电脑重装操作系统后无法访问网络邻居的原因及解决方案,包括检查网络配置、权限设置等多个方面。 ... [详细]
  • 深入解析RAID0、RAID1和RAID5的不同特性及其安全性
    本文详细探讨了RAID0、RAID1和RAID5三种磁盘阵列技术的特点、优势以及它们在数据安全方面的表现。RAID0通过数据条带化提升性能,但牺牲了数据冗余;RAID1利用镜像技术确保数据的高可用性;而RAID5则结合了数据条带化和分布式奇偶校验,提供了较好的性能和数据保护。 ... [详细]
author-avatar
狗狗水灵灵_266
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有