下面是一堆流水帐 慎入:
一. 问题
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数据库,全称为Apache Derby,是Java平台上的一款开源、免费的关系型数据库管理系统,由IBM贡献给Apache软件基金会。作为一款轻量级数据库,Derby以其小巧、高效、易用的特点,深受开发者喜爱,尤其适合于小型...
Derby数据库连接方法详解 Derby数据库连接方法是Java应用程序连接Derby数据库的主要方式。 Derby数据库是一种嵌入式关系数据库管理系统,可以嵌入到Java应用程序中,提供了一个轻量级、可靠的数据库解决方案。 ...
而Apache Derby,作为一个轻量级、开源的关系型数据库,常被用于嵌入式环境,如桌面应用或测试环境。这篇文档将深入探讨如何在Spring Boot项目中集成和使用Apache Derby数据库。 首先,我们需要理解Spring Boot对...
通过配置 derby.properties 文件,可以实现对 Derby 嵌入式数据库的用户验证。具体步骤如下: 1. 在数据库所在目录下创建一个名为 derby.properties 的文件。 2. 在文件中添加以下内容: derby.connection....
4. **数据操作**:Derby支持常见的SQL操作,如INSERT、UPDATE、DELETE和SELECT。例如,插入一条记录:`INSERT INTO Employees VALUES (1, 'John Doe', 'Manager');` 查询所有记录:`SELECT * FROM Employees;` 5. *...
Apache Derby是一款全Java语言编写的开源数据库,设计目标是易用且适用于大多数应用程序。它遵循SQL-92和JDBC 3.0标准,这意味着基于Derby开发的应用程序能够轻松移植到其他兼容这些标准的数据库系统。Derby的目录...
Apache Derby是一款轻量级、嵌入式的关系型数据库管理系统,它是Java编写并完全遵循Java标准JDBC(Java Database Connectivity)的开源数据库。在Java应用程序中使用Derby非常方便,特别是对于那些需要内置数据库...
Derby安装、创建数据库、在JAVA程序中使用Derby Derby是一种嵌入式数据库,可以轻松地嵌入到Java应用程序中。在本教程中,我们将学习如何安装Derby、创建数据库、在Java程序中使用Derby。 安装Derby 首先,我们...
### Apache Derby 数据库使用详解 #### 一、Apache Derby简介 Apache Derby是一款开源的关系型数据库管理系统,它以Java语言编写,能够嵌入到Java应用程序中或任何使用Java平台作为服务器的环境中。Derby的主要...
### Derby中的备份、恢复和前滚恢复 #### 一、备份机制概述 Derby数据库管理系统提供了两种主要的恢复机制:一种是使用全备份使数据库回到备份时的状态;另一种是使用全备份并结合前滚事务日志使数据库恢复到最新...
Apache Derby,是一个开源的、基于Java的嵌入式关系型数据库管理系统(RDBMS),它由Apache软件基金会维护。Derby被设计成轻量级、易于使用,适合于小型应用程序和开发人员。以下是对Derby安装配置与使用的详细介绍...
Derby数据库是一款轻量级的关系型数据库管理系统,由Apache软件基金会开发并维护。它是Java编写,完全符合Java Database Connectivity (JDBC) API的,因此非常适合嵌入式应用和小型项目。本文档将详细介绍Derby...
### Derby安装及嵌入Java初步应用详解 #### 一、Derby简介 Apache Derby是一款开源的轻量级关系型数据库管理系统(RDBMS),它以其简单易用、高性能和易于集成的特点而闻名。Derby支持标准SQL语言,并且能够作为...
Derby是一款开源、轻量级的关系型数据库管理系统,由Apache软件基金会开发并维护。它被设计为嵌入式数据库,适合于Java应用程序。Derby基于Java语言,因此它完全兼容JDBC(Java Database Connectivity),这使得它在...
【标题】"boot-derby:由GitHub Classroom创建的boot-derby" 是一个与计算机启动过程相关的项目,它在x86架构上构建了一个引导加载程序。引导加载程序是操作系统启动过程中的第一部分,其主要任务是加载操作系统内核...
【标题】"Fishing-Derby:我的第一个项目"揭示了一个初学者可能正在尝试构建的简单游戏或模拟程序。钓鱼德比通常是指一种竞赛活动,参赛者在一定时间内捕获尽可能多的鱼。将这个概念转化为编程项目,可能是为了学习...