存档

2009年5月 的存档

JAVA性能优化—编写符合GC胃口的程序

2009年5月30日 hashei 没有评论

JAVA性能优化—IBM JDK JVM参数设置JAVA性能优化—Sun’s Hostspot JVM参数设置两篇文章中我介绍了针对JDK进行优化的方法,这些参数上的改变也许会带来50%甚至100%的性能提升,但是如果从程序入手,可能提升的空间是一个数量级的,而且往往很多时候性能问题光靠调整参数无法解决。接下来分享两篇文档,指点你写出更符合JVM GC“胃口”的代码。

javaProgrammingPerformanceTips

  1. Primitive and Objects
  2. Abuse of the String class
  3. Creating intermediate objects
  4. Mutable return types
  5. Using the wrong collections
  6. Array copy

         GCFriendlyProgramming

  1. Garbage Collection
  2. Programming Tips
  3. Problems With Finalization
  4. Using Reference Objects
  5. Conclusions

          详细内容各位自己看吧,对于编程我也是门外汉。

JAVA性能优化—Sun Hotspot JDK JVM参数设置

2009年5月29日 hashei 5 条评论

本文主要根据这篇PDF(GCTuningGuidelines)写成。

首先是JDK1.5引入的新功能 Ergonomic Settings(自动优化的参数)

对于有2块CPU和2GB内存及更佳配置的服务器,Sun的hotspot jdk默认设置了如下参数:

  • -server :服务器模式编译
  • -XX:+UseParallelGC 并行收集
  • -Xms设置为服务器物理内存的1/64
  • -Xmx设置为服务器物理内存的1/4(最大为1G)

我在网上发现了这篇文章,也是根据那篇PDF写的,基本都翻译过来了,那我就不再做造轮子的过程了。有些自己的想法会用红色标出。

摘自         http://unixboy.javaeye.com/

原文链接 JVM调优总结 -Xms -Xmx -Xmn -Xss

  1. 堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。

    典型设置(例子中的堆分配的都比较大,注意自己平台的限制,下文同)

    • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k-Xmx3550m:设置JVM最大可用内存为3550M。

      -Xms3550m:设置JVM促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存(就是收缩和扩张,分代回收加上Sun内存分配的算法,避免了IBM JDK最小堆和最大堆一样上的缺陷,但是这对-Xms和-Xmx的设置有了更高的要求,应该是多次试验确定一个合适的大小)。

      -Xmn2g:设置年轻代大小为2G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。从下图,应该可以看到整个堆大小=年轻代大小 + 年老代大小,Xms和Xmx不包括Perm Size。

    阅读全文…

WebSphere的类加载机制和故障排查

2009年5月27日 hashei 没有评论

在部署WebSphere应用的过程中,经常会发生诸如:ClassCastException、ClassNotFoundException、NoClassDefFoundException、UnsatisfiedLinkError的错误。这种有关“类”(Class)的错误,往往来无影——开发环境好的,怎么在生产环境就有问题;而且去无踪——单独建立一个Profile部署一下就没问题了,把Jar包换个目录就OK了。其实要解决这些怪异的问题,首先要了解WebSphere的类加载(Class loader)机制。

下文主要内容来自http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=/com.ibm.websphere.nd.doc/info/welcome_nd.html 和IBM developworks中的《如何在WebSphere中解决jar包冲突》一文,我把个人觉得最容易理解的部分总结在一起,方便学习和快速的解决问题。

使用的类装入器以及使用顺序

WebSphere Application Server 的运行时环境按以下顺序使用下列类装入器来查找和装入应用程序的新类:

  1. Java 虚拟机创建的引导程序、扩展和 CLASSPATH 类装入器引导程序类装入器使用引导类路径(通常是 jre/lib 中的类)找到并装入类。扩展类装入器使用系统属性 java.ext.dirs(通常是 jre/lib/ext)找到并装入类。CLASSPATH 类装入器使用 CLASSPATH 环境变量查找和装入类。CLASSPATH 类装入器装入 WebSphere Application Server 产品在 j2ee.jar 文件中提供的 Java 2 Platform, Enterprise Edition(J2EE)应用程序编程接口(API)。由于这个类装入器装入 J2EE API,所以,可以将依赖于 J2EE API 的库添加到类路径系统属性中以扩展服务器类路径。但是,扩展服务器的类路径的首选方法是添加共享库
  2. WebSphere 扩展类装入器WebSphere 扩展类装入器装入在运行时需要的 WebSphere Application Server 类。扩展类装入器使用 ws.ext.dirs 系统属性来确定装入类时所使用的路径。ws.ext.dirs 类路径中的每个目录和这些目录中的每个 Java 归档(JAR)文件或 ZIP 文件都添加到此类装入器使用的类路径中。如果安装在服务器上的应用程序模块引用了与资源提供程序相关联的资源,并且该提供程序指定了资源驱动程序的目录名称,那么 WebSphere 扩展类装入器还将资源提供程序类装入到服务器中。
  3. 一个或多个应用程序模块类装入器,它们负责装入在服务器中运行的企业应用程序的元素应用程序元素可以是 Web 模块、企业 bean(EJB)模块、资源适配器归档(RAR 文件)和依赖项 JAR 文件。应用程序类装入器按照 J2EE 类装入规则从企业应用程序装入类和 JAR 文件。WebSphere Application Server 允许使共享库与应用程序相关联。
  4. 零个或多个 Web 模块类装入器缺省情况下,Web 模块类装入器装入 WEB-INF/classes 和 WEB-INF/lib 目录的内容。Web 模块类装入器是应用程序类装入器的子代。可以指定使用应用程序类装入器来装入 Web 模块的内容,而不是使用 Web 模块类装入器来装入这些内容。

阅读全文…

抵抗诱惑——系统管理员的时间管理

2009年5月26日 hashei 没有评论

       I Can Resist Everything Except Temptation

                                                                —— Oscar Wilde

       最近工作比较清闲,就免不得胡思乱想,想个人今后的职业发展,想如何更好的利用现在这段还算年轻自由的时光。“年轻人是不是应该为梦想殊死搏斗?”这是某位老大的疑问。如果说梦想是隐隐绰绰,看的见却抓不着,或者只是留下“别和我谈理想,已经戒了”的无奈,那么一个切实可行的目标总该有的吧。谁不想在公司里成为举足轻重的骨干,谁不愿兜里的钱能多一些,谁不希望有个幸福美满的家庭?

       我是都想的,看看离而立之年只有5年的时光,总感到一阵阵紧迫感。但是自己这种天塌下来都悠哉游哉的性格,做啥事一会会后就想着“不要着急不要着急,休息休息一下”的半吊子态度,让我自己都觉得实在是可恶至极。

其实我们都知道自己的弱点,但是知道是一回事,克服又是另一回事了——至少在没有旁人督促的情况下。而当我看到这本《时间管理-给系统管理员》的时候,我知道了督促的关键不是是否有个人一直在背后催着,而是是否有一个完善的计划。

  1. 切实可行的长期计划(个人和职业)
  2. 如何在8小时内安排好100小时任务量的计划——优先级管理
  3. 如何专心工作,避免打扰的计划
  4. 如何不会被会议、邮件占用整个一天的计划
  5. 如何避免把时间都浪费在“开心网”上的计划
  6. 如何把自己的大脑从繁杂的记忆中解放出来的计划

……

时间管理的关键就是GTD(Get things Done),现在已不新鲜,但从此书中点出则让我倍感亲切,因为它是一本针对我的书——Time Managerment for System Administrators。但是要谨记的一点是:养成一个习惯需要21天。所以如何避免一暴十寒是我接下去能否成功的重点。

现在我面临的诱惑很多:每天“开心网”的偷菜种菜、转帖的八卦新闻,订阅的大量博客,MSN上闪闪发亮的头像。所以执行力(又见执行力)是关键。可以说,我现在开的这个博“聚沙成塔—小哈的记事簿”,也是贯彻执行力的一个手段。唯有要把自己的知识写出来而又不贻笑大方,才能逼着自己查阅原始资料,务必找到官方明确描述的语句,逼着自己为了理解一些繁琐的英语长句请教英语系的高材生。书写是为了更好的思考为什么你应该(从现在开始就)写博客是我坚持下去的动力,而“刘未鹏 | Mind Hacks 思维改变生活”也必将不会被清理出我的google reader(大家可以看看,他的每一篇文章都可以说是精工细作的结果)。

这篇文章虽说夹杂着人生计划,可到底还是一篇读后感,所以也不得不吐槽一下“糟糕”的翻译。文中时时夹杂着生硬的如机器翻译的语句,如“我是一个新鲜人”,那些每章开头都有的漫画我也没看出什么笑点来。不过万幸的是,这不是一部文学作品,而且有意思的是,如果你读到无法理解的句子,试着将它译回英文(一个词一个词翻译就好了)你会豁然开朗。

WebSphere遗忘管理控制台密码怎么办?外一篇其它各种密码的补救措施

2009年5月25日 hashei 没有评论

常在河边走,哪有不湿鞋,WebSphere管理中最让人无语的是把密码忘记了。管理控制台也好,数据源的密码也好,配置的时候为了满足安全管理的要求设置了8位以上、大小写皆有、毫无意义的密码,现在两眼一抹黑,怎么都试不出来。怎么办?重装?生产环境好不好。其实不用着急,IBM还是给我们留了一条后路的。

管理控制台密码遗忘有两种补救措施:

方法一:命令行——从$WAS_HOME/profiles/xxx 概要文件名/bin目录下,运行 wsadmin -conntype NONE 。当wsadmin的命令行窗口出现之后,运行 securityoff 。上述操作在应用服务器启动或停止的状态都能发出。再次启用WAS时,就是停用管理安全性的状态了。

方法二:修改配置文件——修改$WAS_HOME\config\cells\xxx 下的security.xml,把第一个enable改成false就取消安全性了。

详细说明 http://www-01.ibm.com/support/docview.wss?uid=swg21105430

以上两种方法是禁用了全局安全性(global security),最后别忘了设置新的密码然后再次启用。

下文是讲述如何“破解”出WebSphere中其它密码的方法:

转自Sunny’s 部落格

http://www.sunnyblog.info/blog/archives/3149

WebSphere会在配置文件(一堆的XML)当中存放各种密码(包括数据源、认证别名等等),例如在$WAS_Profile_HOME\config\cells\security.xml文件里面有类似”<authDataEntries xmi:id=”JAASAuthData_1238489272531″ alias=”myNode01/oracleDBA” userId=”oraadmin” password=”{xor}bm1sa2pp”/>”,就是存放认证别名为oracleDBA的用户名和密码。

可以看到在这里密码被重新编码(encode)了,编码的方式是XOR(eXclusive OR异或),很明显这种并不是一种强加密的算法,仅仅是一种编码而已,所以准确来说WebSphere为了避免密码被明文记录,只是很简单地“编码”(encode)而不是“加密”(encrypt)。

万一阁下一个不小心忘记了存放在WebSphere里面的密码,但是又想恢复过来的话,WebSphere这种只是编码而不是加密的存放密码形式,就帮助了你了。当然如果你想干坏事的话,WebSphere也算是给自己留下了一个“后门”了 -_-b。嘿嘿嘿,不要以为IBM那帮老爷子就是这么懒,如果阁下真的是要对存放在WebSphere配置文件里面的密码要加密的话(对于广大客户肯定是有这个诉求的),其实IBM也提供了一种自定义加密算法的插件形式去解决这个问题的,详情可以参考这个链接,在这里就不对这个问题进行展开讨论了。

好了,现在就对各个版本的WAS的密码编码和反编码进行讨论:

WAS 5.X的编码:

> cd $WAS_INSTALL_DIR/lib
> ../java/bin/java -cp securityimpl.jar:iwsorb.jar com.ibm.ws.security.util.PasswordEncoder 123456

WAS 5.X的反编码:

> cd $WAS_INSTALL_DIR/lib
> ../java/bin/java -cp securityimpl.jar:iwsorb.jar com.ibm.ws.security.util.PasswordDecoder {xor}bm1sa2pp

WAS 6.0的编码:

> cd $WAS_INSTALL_DIR/lib
> ../java/bin/java -cp securityimpl.jar:iwsorb.jar::ras.jar:wsexception.jar:bootstrap.jar:emf.jar:ffdc.jar com.ibm.ws.security.util.PasswordEncoder 123456

WAS 6.0的反编码:

> cd $WAS_INSTALL_DIR/lib
> ../java/bin/java -cp securityimpl.jar:iwsorb.jar::ras.jar:wsexception.jar:bootstrap.jar:emf.jar:ffdc.jar com.ibm.ws.security.util.PasswordDecoder {xor}bm1sa2pp

WAS 6.1的编码:

> cd $WAS_INSTALL_DIR/bin\ProfileManagement\plugins\com.ibm.websphere.v61_6.1.200
> java -cp ws_runtime.jar com.ibm.ws.security.util.PasswordEncoder 123456

WAS 6.1的反编码:

> cd $WAS_INSTALL_DIR/bin\ProfileManagement\plugins\com.ibm.websphere.v61_6.1.200
> java -cp ws_runtime.jar com.ibm.ws.security.util.PasswordDecoder  {xor}bm1sa2pp

以上内容参考转载自robertmaldon

当然,如果你觉得很麻烦的话,其实也有一个网站直接帮你解码:WebSphere Password Decoder

JAVA性能优化—IBM JDK JVM参数设置

2009年5月23日 hashei 4 条评论

前一篇JVM的恩恩怨怨中,说了对WebSphere优化的关键点——因不同JDK而异。本文将描述IBM JDK下常用参数的设置。

-Xms:最小堆大小

-Xmx:最大堆大小

-Xminf and -Xmaxf:GC(垃圾回收)之后可用空间的最小值最大值

-Xmine and -Xmaxe:堆增长的最小最大值

-Xmint and -Xmaxt:垃圾回收占时间整个运行时间的比例,默认是5%。如果回收时间小于5%,那么它就缩减堆,反之增大。

一般来说只要对Xms和Xmx设置合理,后面的三对不用特别设置。可以看看http://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp上heap expasion和heap shrinkage两章的说明,除非有下文的情况:

如果使用大小可变的堆(比如,-Xms 和 -Xmx 不同),应用程序可能遇到这样的情况,不断出现分配失败而堆没有扩展。这就是堆失效,是由于堆的大小刚刚能够避免扩展但又不足以解决以后的分配失败而造成的。通常,垃圾收集周期释放的空间不仅可以满足当前的分配失败,而且还有很多可供以后的分配请求使用的空间。但是,如果堆处于失效状态,那么每个垃圾收集周期释放的空间刚刚能够满足当前的分配失败。结果,下一次分配请求时,又会进入垃圾收集周期,依此类推。大量生存时间很短的对象也可能造成这种现象。避免这种循环的一种办法是增加 -Xminf 和 -Xmaxf 的值。比方说,如果使用 -Xminf.5,堆将增长到至少有 50% 的自由空间。同样,增加 -Xmaxf 也是很合理。如果 -Xminf等于0.5,-Xmaxf 为默认值 0.6,因为 JVM 要把自由空间比例保持在 50% 和 60% 之间,所以就会出现太多的扩展和收缩。两者相差 0.3 是一个不错的选择,这样 -Xmaxf.8 可以很好地匹配 -Xminf.5。如果记录表明,需要多次扩展才能达到稳定的堆大小,但可以更改 -Xmine,根据应用程序的行为来设置扩展大小的最小值。目标是获得足够的可用空间,不仅能满足当前的请求,而且能满足以后的很多请求,从而避免过多的垃圾收集周期。-Xmine、-Xmaxf 和 -Xminf 为控制应用程序的内存使用特性提供了很大的灵活性。

摘自Java性能优化的策略和常见方法

所以在应用正式上线的头一段时间,最好把GC日志打开,观察一下堆(heap)的增长(expasion)和收缩(shrinkage)。最佳的情况就是,每次回收后可用的堆大小占整个堆的50%左右。如果回收后才腾出30%不到的可用空间,那就该再调整一下上述的参数了。下图看起来直观一点,使用-verbose:size参数可以查看当前的默认值。

IBM WAS Heap Sizes

那为何不把Xms和Xmx设置成一样大,就像SUN的JDK所推荐的那样?

Using the same values is not usually a good idea, because it delays the start of garbage collection until the heap is full. The first time that the Garbage Collector runs, therefore, becomes a very expensive operation. Also, the heap is more likely to be fragmented and require a heap compaction. Again this is a very expensive operation.……

If the Garbage Collector cannot find enough garbage, it runs compaction. If the Garbage Collector finds enough garbage, or any of the other conditions for heap expansion are met , the Garbage Collector expands the heap.

因为IBM JDK采用的是标记(mark)-扫描(sweep)-标记-……-扫描-紧凑排列(compact),如果还不能提供足够的空间,扩展堆(expasion)。依次循环,直到达到最大堆大小。每次扩展前,那些长存的对象就被调整到堆的底部,每次扩展后需要再动的量就很少。所以如果把Xms设置成和Xmx一样,那么扫描和紧凑排列这么一个充满内存碎片的大堆的开销将大大高于从小扩展堆的开销。

The overheads of expanding the heap are almost trivial compared to the cost of collecting and compacting a very large fragmented heap.

这是由于IBM的GC特点造成的,而SUN的JDK采用的是分代回收的策略,所以就没有这种情况,反而会受益于堆大小一致。不过这么说起来,用了-Xgcpolicy:gencon,就应该把最小堆最大堆设置成一样咯。

在Gencon回收策略下,可以通过-Xmn来设置婴儿区域(Nursery或者叫young)的大小,通过-Xmo来设置长存区(tenured或者old)的大小。注意-Xmn不能和-Xmns/-Xmnx参数一起使用,-Xmo不能和-Xmos/-Xmox一起使用,否则会报错。前者就是把年轻代和长存代的大小固定了,而后两者就是设定两个部分最大最小的范围,默认情况下:

-Xmns是-Xms的25%或者64M(在JDK 5.0中默认是25%)

-Xmnx是-Xmx的25%或者64M(同上)

-Xmos是-Xmx减去-Xmns的大小

-Xmox是和-Xmx一样大

可见默认的年轻代太小了,生产环境中有必要改大一点。因为年轻代使用的是复制策略,所以回收速度相当快(minor gc),而长存代使用的是和optavgpause 策略相似的方式进行并发标志、扫描策略,回收速度比较慢(major gc)。理想情况是minor gc和major gc的比值在1:1010:1左右。(可以通过GC日志查看回收的区域)

gencon中年老期限(Tenure age)和倾斜比率(Tilt ratio)这两个参数是JVM自己动态调整的。

针对固定对象问题(Pinned Objects),使用-Xk -Xp参数设定kCluster和pCluster,Avoiding Java heap fragmentation with Java SDK V1.4.2. 或者我这篇IBM JDK的Java堆空间的碎片问题

一些不常用的参数:

-Xloainitial<percentage> -Xloamaximum<percentage> :调整大对象区域(Large Object Area)的大小。分配总是先在SOA(Small Object Area)中分配,如果没有空间并且需要分配的大小大于64K,那么分配到LOA。默认情况下为-Xloainitial0.05 (5%),-Xloamaximum0.5 (50%),如果你的程序确实需要分配许多大对象的话(大于64K),那么可以调整LOA的初始百分比。

以上两点可以参考我这篇IBM JDK的Java堆空间的碎片问题,获得更详细的解释。

总结一下来说,对于optthruput和optavgpause,设置恰当的最大堆和最小堆,设置-Xk和-Xp避免碎片问题,如果程序需要分配大对象较多,那么调整一下LOA的大小;对于gencon,可以调大最小堆和最大堆接近,调整young区域的大小,LOA也可以视情况调整。subpool一般用不到,就不去研究了。

一些另外的信息

Default settings for the JVM

http://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp?topic=/com.ibm.java.doc.diagnostics.50/diag/appendixes/defaults.html

JVM environment settings

http://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp?topic=/com.ibm.java.doc.diagnostics.50/diag/appendixes/env_var/env_jvm.html

默认的Heapdumps是关闭的,调试的时候记得打开;默认的Javadumps on out of memory和Heapdumps on out of memory都是开启的,但是默认的dump位置是profile的所在目录,最好在管理控制台java进程中把IBM_HEAPDUMPDIR和IBM_JAVACOREDIR设置到别的目录,防止dump内容把WAS的文件系统撑爆,影响正常业务使用。

在Windows机器上,如果内存大于4G,记得开启/3GB参数,这样可以使JVM Heap可以设置的更大一些,接近2G-1,(其它的三部分可以扩展到另外的1G上去),但一般最大不超过1.7G。

Memory layout of a vm in the os

更详细内容,可见http://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp

或者下载dig60 http://www.ibm.com/developerworks/java/jdk/diagnosis/查看JVM这一块

Sun的JDK配置,可以参考JAVA性能优化—Sun Hotspot JDK JVM参数设置