浏览 9233 次
精华帖 (1) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-12-17
近来因为项目紧张,服务器用的人多了,出现内存不足,top显示使用了约500M的swap空间,频繁出现java out of memory,tomcat经常死机,严重影响工作。而且还出现晚上不能重新启动的问题,早上过来服务器不可用,影响一天心情。 上周向公司申请了采购了几根1G的内存,这台服务器只分到一根1G条,且只有两根内存插槽,将就一下,升级到1.5G内存,同时了解到Bea JRockit已经解决了PermSize的问题,决定使用jrockit vm试试,结果出乎我意料的好。 我下载的是jrockit sdk 6.0,在linux上设置JAVA_HOME指向安装目录,并把$JAVA_HOME/bin加到PATH变量,修改catalina.sh,在前面加入: JAVA_OPTS="-server -Xms256M -Xmx576M" jrockit已经不需要-XX:PermSize这样的参数了。 使用一个星期以来,Tomcat从来没有死过,内存使用一直稳定在565M左右,系统总内存稳定在1480M左右,相当的稳定,而且java应用的速度感觉有很大的提高。 总体来说,我全力推荐在生产应用服务器上使用jrockit vm,它会给你带来意想不到的惊喜。但本地开发我还是选择使用sun java sdk,在我的开发机上,jrockit吃内存相对厉害,而我只有1G的内存。 注:所谓PermSize,是指vm为类描述信息分配的内存空间,随着动态类等技术的广泛应用,这一内存区默认的64M大小已经不能满足需要,而且,sun vm对这部分内存居然无法进行gc,所以需要设置一个比较大的PermSize。但长时间运行后特别是频繁进行JavaEE应用部署的话,仍然会出现out of memory异常。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-12-17
bea 真的有这么好吗?我想问一下,你的java文件需要用bea jrockit重新编译一下吗?
|
|
返回顶楼 | |
发表时间:2007-12-17
没有,不需要,java编译出来的.class是二进制兼容的。
|
|
返回顶楼 | |
发表时间:2007-12-17
我撇开你使用jrockit带来的好处,纯粹和你讨论为什么你在Sun jdk下跑这么喘
首先丢给你个问题:动态类(proxy,cglib...)只能一次性的吗?是不可再重复利用的吗?如果是可重复利用的,那这些数据还是有一个极限的,不需要操心去GC它们。 (我自己动手实践的结果是: Proxy.newProxyInstance(...)只要是代理同样的接口则proxy类(名)是一样的,见后代码) 虽然,有可能一些不良程序可能会不断建立不同的动态类给同一个接口或类。但是仅从你提供的帖子的信息看,我认为你的问题不是动态类带来的,除非有其他证明(数据说明)。 假如这个前提成立的话,那就继续以下的分析: 你的perm空间占用实际值却是不断增大(以致你要调到256m),说明你older空间不断“升级”对象给perm,如果older持续上来对象,perm space将吃不消。到一定程度时,perm space用差不多了,older对象又想上来就上不来了,此时new genneration等不到older腾出空间,这就出现植物人现象 或out of memory之类的现象了。 所以问题的实质是:到底是些什么导致older对象这么多,不断往上跑,而使jdk gc无法gc到它们? package net.paoding.proxytest; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Main { interface A { public String hello(); } interface B { public String hello(); } public static void main(String[] args) { for (int i = 0; i < 3; i++) { A p = getA(); System.out.println(p.getClass().getName()); System.out.println(p.hello()); System.out.println("-------------"); } for (int i = 0; i < 3; i++) { B p = getB(); System.out.println(p.getClass().getName()); System.out.println(p.hello()); System.out.println("-------------"); } } private static A getA() { A p = (A) Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[] { A.class }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return "hello A"; } }); return p; } private static B getB() { B p = (B) Proxy.newProxyInstance(Main.class.getClassLoader(), new Class[] { B.class }, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return "hello B"; } }); return p; } } net.paoding.proxytest.$Proxy0 hello A ------------- net.paoding.proxytest.$Proxy0 hello A ------------- net.paoding.proxytest.$Proxy0 hello A ------------- net.paoding.proxytest.$Proxy1 hello B ------------- net.paoding.proxytest.$Proxy1 hello B ------------- net.paoding.proxytest.$Proxy1 hello B ------------- |
|
返回顶楼 | |
发表时间:2007-12-17
如何设置,让jdk和jrockit共存,jdk和jrockit的版本要完全一致吗,比如是1.5.6,两者都要一样吗!
|
|
返回顶楼 | |
发表时间:2007-12-18
回复Qieqie:
qieqie是“庖丁解牛”框架的作者吧,久仰。 查了一下资料,我记错了数据,默认PermSize是64M。 这个问题我之前也想过,Permanent Generation保存了JVM中所有对象的类信息,包括类的元数据,还有方法描述等等,毕竟sun设置默认PermSize也是认为这堆空间会达到一个上限后不再上升,但是,在Java大程序的情况下,尤其是Java EE的大型应用程序上,Permanent Generation的大小会直接限定能载入类的数量和大小。现代java应用程序使用的jar包动辄几十M,部署近10个web应用,内置的不同版本的jar包,加上jsp生成的类、各类框架生成的动态类(Hibernate、Spring大量使用这类技术,动态代理是现代框架的一个重要特点),类的数量十分可观。我觉得内存一直上升的原因是java是延迟加载的,在使用过程中加载出不同的模块(jar),因为应用比较多而出现Perm不足,这时设置更大的PermSize也许会解决问题。 而且,据我的经验,使用sun vm,多次重新生成并部署war模块,达到一定次数后,不管是tomcat还是weblogic,应用服务器都会出现Out of memory,屡试不爽。这也是重新部署后类的描述信息更新了,旧的类描述不能释放造成的。 |
|
返回顶楼 | |
发表时间:2007-12-18
答复tangyuanjian:
无须特殊的设置,可以共存。共存也不需要jdk版本一致,但jdk6编译的.class是不能在jrockit5上运行的,只能在jrockit6上运行。 我一般是设置JAVA_HOME,并把JAVA_HOME/bin设置到PATH的第一位,这样切换jdk时,只需要修改JAVA_HOME的值就可以了。 |
|
返回顶楼 | |