下面是一堆流水帐 慎入:
一. 问题
Java GC 监视方法与工具
中写道,我们的项目出现了Out Of Memory问题。
现在这个问题看来可能是由Derby引发的。
项目中使用的derby版本是10.1,而且还是beta版的。Liu同学google到的信息,这个版本有内存泄露:
Bug Fixes of Derby10.2.2
OutOfMemory error on continuous execution of SQL statement
10.2.2的release中说修复了这个bug。但由下列描述:
写道
After fixing the original memory leak, I still run into problems on repeated execution of a sql statement. Take the sample program in the bug and run it with a small heap size (4m). After around 80-90K
executions an outofmemory error is thrown. I took snapshots of the heap while the program was running but couldn't find anything obviously wrong.
看来这个bug貌似修完了还有问题,需要测一下,因为我们要插入190k的数据一次。
二. Derby升级
为此我们做了一次Derby的升级。
我们的应用跑在SunAS 8里面,试了一下,按如下步骤升级:
1. 导出以前数据库的表结构和配置信息。
2. 使用10.4的derby创建新数据库。
在工程空间里面能够跑起来,可到SunAS 8里面便无法运行。抛出下面的异常:
写道
[#|2009-03-30T14:54:54.700+0800|严重|sun-appserver-pe8.0.0_01|javax.enterprise.system.container.web|_ThreadID=10;|WebModule[/psv2]Exception sending context initialized event to listener instance of class com.okidata.common.InitDB
java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:141)
at com.okidata.common.DBConnectionManager.loadDrivers(DBConnectionManager.java:873)
at com.okidata.common.DBConnectionManager.init(DBConnectionManager.java:814)
at com.okidata.common.DBConnectionManager.<init>(DBConnectionManager.java:448)
at com.okidata.common.DBConnectionManager.<clinit>(DBConnectionManager.java:55)
at com.okidata.common.InitDB.contextInitialized(InitDB.java:76)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3659)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4120)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1089)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:760)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1089)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:467)
at org.apache.catalina.startup.Embedded.start(Embedded.java:986)
at com.sun.enterprise.web.WebContainer.start(WebContainer.java:490)
at com.sun.enterprise.web.PEWebContainer.startInstance(PEWebContainer.java:506)
at com.sun.enterprise.web.PEWebContainerLifecycle.onStartup(PEWebContainerLifecycle.java:54)
at com.sun.enterprise.server.ApplicationServer.onStartup(ApplicationServer.java:295)
at com.sun.enterprise.server.PEMain.run(PEMain.java:220)
at com.sun.enterprise.server.PEMain.main(PEMain.java:172)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.apache.commons.launcher.ChildMain.run(ChildMain.java:269)
Caused by: java.lang.SecurityException: Sealing violation loading org.apache.derby.jdbc.InternalDriver : Package org.apache.derby.jdbc is sealed.
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1722)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:904)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1370)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
at org.apache.derby.iapi.jdbc.JDBCBoot.boot(Unknown Source)
at org.apache.derby.jdbc.EmbeddedDriver.boot(Unknown Source)
at org.apache.derby.jdbc.EmbeddedDriver.<clinit>(Unknown Source)
... 25 more
网上有说是load了两个derby.jar,
但我们调查了不是这个原因.
起初我们以为是class的版本不兼容, 以为是SunAS 8的jdk是1.4.0,而derby10.4要求1.5以上了。
但是看了一下Derby的官方文档, 10.2.2的Release Notes
有下列描述:
JDK/JDBC support:
* JDKs 1.3, 1.4, 1.5, and 1.6 plus J2ME J2ME/CDC/Foundation Profile
* JSR-169, JDBC 2.1, JDBC 3.0, and JDBC 4.0 support
看来这个版本不兼容的问题可以排除了.
回头我们再整理思路:
我们的程序有前后台之分, 我们所谓的前台是SunAS, 后台是我们自己的程序.
现在Derby的启动工作由前台来做, 后台使用网络连接的方式访问该数据库.
问题的原因可以肯定是什么地方不兼容了, 因为我们的前后台程序在工程空间中跑, 在tomcat中跑, 没有任何问题,
那么会不会是derby和SunAS不兼容? Liu同学再一次大胆而机敏的建议,
让后台启动derby, 前台通过网络的方式访问数据库如何.
尝试之, 正解是也!
nnd, 同样的方式, 启动同样Derby, 我们的后台(自己写的一个jar, 然后java -jar)启动没问题.
配置到web.xml里, 作为一个ServletContextListener去执行,我想不是ServletContextListener的限制,
因为在tomcat里面这么做是没有问题的,在contextInitialized可以很好的启动Derby
所以我们最后只好把它定义成"Sun Application Server 8的一个bug"
我们都被折腾得够呛, 因为从我们自己的bug, 折腾到derby的bug, 再折腾到SunAS的问题,
这一圈,确实有点绕. 不过还好, 总算成功的给他升了级, 接下来的便是测试结果.
三. 升级后测试结果.
升级到Derby10.2之后,有提高,但依旧Out Of Memory.
实际环境中, 每小时做一次19W的插入操作, 跑了两天, 他还是挂掉了.
因为堆大小使用的是默认64M, 所以也不确定是某些原因造成内存确实不够(如数据库变大之类), 还是有溢出.
反正也是升级, 还不如升到10.4正式版
升级到10.4之后
第一个晚上, Liu同学在他的电脑上,jprofile里,循环跑了180回左右, 搞出了个OOM, 我们很郁闷,
结果后来Liu同学发现这个OOM是jprofile的,
还好, 总算松了口气, 调大内存接着来~
让Derby单独一个虚拟机启动, 我们的应用使用默认64M堆大小, 数据库插入到12G左右, 跑了400来回
从jprofile的数据看, 没有内存溢出现象.
至此我们的问题总算算是圆满解决.
ps. 没有升级以前, 上述环境下内存溢出非常明显, 且与数据库大小有关系, 越大溢出越快, 这也是我们在另一台机器上的测试结果.
四. 总结.
Derby10.1在大批量持续插入时候, 有OOM的bug,
解决办法:
1. 优化我们的程序, 要是到对19W的ArrayList在19W的循环里,循环调用trimToSize可不是什么好事,
即使每次都会remove掉一个元素,而这一切只是为了得到一个打印机列表.
2. 升级Derby.
3. 使用"-Xms256m -Xmx256m" 调大我们应用的堆大小.
分享到:
相关推荐
Risk Analysis of a pinewood derby: A case study Risk Analysis of a Pinewood Derby: A Case Study A. Terry Bahill1,* and William J. Karnavas2 1Systems and Industrial Engineering, University of ...
derby数据库,java自带的,轻量级简单好用。
春天引导德比Apache Derby嵌入式数据库的Spring Boot Java技术员
derby:纯Java编写的嵌入式数据库
derby的eclipse插件 博文链接:https://hugebait.iteye.com/blog/47188
Derby - Bourbon / Neat Autocompletion for Sublime Text 崇高的自动完成功能可帮助您在项目中使用和 。 以含有石灰和波旁威士忌的鸡尾酒德比命名。 特别感谢提供最新更新。没有包控制的安装如果要在没有包控制的...
收集的学习资料,包括:Derby数据库(V10.9)用户手册(PDF版),用 Apache Derby 进行 Java 数据库开发,用 Apache Derby 进行数据库开发,03开源项目(三)嵌入式数据库Apache Derby(1)(开发指南).pdf ,Apache Derby ...
肥皂盒赛车组装自己的肥皂盒,看看它能走多快!从一系列不同的零件中进行选择,并打造您从未有过的梦想之车。没有动物被帮助制作这个游戏。
引导德比 在程序集x86中制成的引导程序,可以缓慢键入内容。 这也非常友好:)
Derby数据库完整压缩包,解压缩即可使用,bat文件在bin文件目录下,驱动程序在lib目录下。 Apache Derby非常小巧,核心部分derby.jar只有2M,所以既可以做为单独的数据库服务器使用,也可以内嵌在应用程序中使用。...
Derby MVC框架使编写可在Node.js和浏览器中运行的实时协作应用程序变得容易。 Derby包含一个强大的数据同步引擎,称为Racer,可自动在浏览器,服务器和数据库之间同步数据。 模型订阅特定对象的更改,从而无需定义...
钓鱼德比 我的第一个项目
Eclipse插件Derby安装 Derby插件开发
derby_plugin derby_ui_plugin derby Eclipse插件
第一:derby集成到eclipse的两种方法 第二:derby辅助工具SQuirreL SQL Client的使用