该程序是用Spring定时器执行的,定时用hibernate框架查询数据库,将查询到的结果写成文本文件。
启动定时器之后每次在生成了52个文本文件之后,就内存溢出了。
由于代码不多我直接贴代码和错误提示吧!
希望各位高手有时间帮忙看一下!
下面的是定时器执行的类和方法
public class BillInfoExporter {
private static String[] LOCATIONS = { "spring-hibernate.xml", "spring-minidao.xml" };
private Map<String, String> config;
protected final static Logger logger = Logger.getLogger("log4j.properties");
@SuppressWarnings("unused")
public boolean billInfoExport() {
ApplicationContext ctx = null;
BillingService billingService = null;
TextFileWriter textFileWriter = null;
File file = null;
List<Map> ioGoods = null;
List<Map> selfGoods = null;
try {
if (ctx == null) {
ctx = new ClassPathXmlApplicationContext(LOCATIONS);
if (billingService == null) {
billingService = (BillingService) ctx.getBean("billingServiceImpl");
}
}
StringBuffer buff = new StringBuffer();
ioGoods = billingService.billingIOGoodsMessage();
BillExporterUtils.billExport(buff, ioGoods);
selfGoods = billingService.billingSelfGoodMessage();
BillExporterUtils.billExport(buff, selfGoods);
file = new File(buildFileName());
textFileWriter = new TextFileWriter(file, false);
textFileWriter.outPut(buff.toString());
buff = null;
return true;
} catch (Exception e) {
String resultLog = "未能成功从数据库中查询自用物资、备案清单进出单号信息,当前系统日期为:" + CalendarUtils.formatDate(new Date());
logger.error(resultLog, e);
} finally{
try {
if(textFileWriter!=null){
textFileWriter.closeFile();
textFileWriter = null;
}
if (ioGoods != null) {
ioGoods = null;
}
if (selfGoods != null) {
selfGoods = null;
}
System.gc();
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
private String buildFileName(){
String fileName = null;
StringBuffer sBuffer = new StringBuffer();
Date currentDate = new Date();
fileName = config.get("outputPath");
if (StringUtils.isBlank(fileName)) {
fileName = System.getProperty("user.dir") + "/output";
System.out.println(fileName);
}
sBuffer.append(fileName).append("/");
sBuffer.append("SB_");
sBuffer.append(CalendarUtils.format(currentDate, "MM")).append('_');
sBuffer.append(currentDate.getTime());
sBuffer.append(".bi");
fileName = sBuffer.toString();
return fileName;
}
public Map<String, String> getConfig() {
return config;
}
public void setConfig(Map<String, String> config) {
this.config = config;
}
}
下面是加载Spring定时器的主函数类
public class BillInfoScheduler {
public static void main(String[] args) {
try {
String configFile = null;
if(args!=null && args.length>0){
configFile = args[0].trim();
}else{
configFile = "scheduler.xml";
}
execute(configFile);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void execute(String configFile){
ApplicationContext ctx = new ClassPathXmlApplicationContext(configFile);
}
}
下面是定时器的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 第零步: 配置计费信息输出的路径 -->
<bean id="config" class="java.util.HashMap">
<constructor-arg>
<map>
<entry key="outputPath" value="D:/work_dev/YanKe/Source/ECLink_packed/output" />
</map>
</constructor-arg>
</bean>
<!-- 第一步: 配置好要定时调用的业务类 -->
<bean id="billInfoExporter" class="org.broadengate.eclink.schedule.BillInfoExporter">
<property name="config" ref="config" />
</bean>
<!-- 第二步: 定义好具体要使用类的哪一个业务方法 -->
<bean id="printTimerJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 目标bean -->
<property name="targetObject" ref="billInfoExporter" />
<!-- 要执行目标bean的哪一个业务方法 -->
<property name="targetMethod" value="billInfoExport" />
<!-- 是否并发 -->
<property name="concurrent" value="false" />
</bean>
<!-- 第三步: 定义好调用模式: 如每隔2秒钟调用一次或每天的哪个时间调用一次等 -->
<bean id="printTimerTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="printTimerJob" />
<property name="cronExpression" value="0/2 * * * * ?" />
<!-- 每月最后一日的上午10:15触发 0 15 10 L * ? -->
<!-- 每天晚上23:00触发 0 0 23 * * ? -->
</bean>
<!-- 启动定时器 -->
<!--第四步 把定义好的任务放到调度(Scheduler)工厂里面,注意这里的ref bean -->
<bean id="schedulerFactoryBean"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
<property name="triggers">
<list>
<ref bean="printTimerTrigger" />
</list>
</property>
</bean>
<!-- end -->
</beans>
控制台报的错,是说我在执行定时任务的方法是时由于内存溢出而无法执行吗?
[org.quartz.core.JobRunShell]Job DEFAULT.printTimerJob threw an unhandled Exception:
org.springframework.scheduling.quartz.JobMethodInvocationFailedException: Invocation of method 'billInfoExport' on target class [class org.broadengate.eclink.schedule.BillInfoExporter] failed; nested exception is java.lang.OutOfMemoryError: PermGen space
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:320)
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:113)
at org.quartz.core.JobRunShell.run(JobRunShell.java:216)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
Caused by: java.lang.OutOfMemoryError: PermGen space
BillInfoExporter是定时器调用的类,billInfoExport()是定时器执行的方法。
原先,我在billInfoExport()方法中创建Spring的ApplicationContext对象,并且通过它获得我要使用的Service类对象。
这样一来,每次定时器调用该方法都去初始化Spring,创建很多Bean实例。于是就内存溢出了……
修改后的代码:
public class BillInfoExporter {
private static String[] LOCATIONS = { "spring-hibernate.xml",
"spring-minidao.xml" };
private Map<String, String> config;
protected final static Logger logger = Logger.getLogger("log4j.properties");
private static ApplicationContext ctx = null;
private static BillingService billingService = null;
static{
if (ctx == null) {
ctx = new ClassPathXmlApplicationContext(LOCATIONS);
if (billingService == null) {
billingService = (BillingService) ctx.getBean("billingServiceImpl");
}
}
}
@SuppressWarnings("unused")
public boolean billInfoExport() {
TextFileWriter textFileWriter = null;
File file = null;
List<Map> ioGoods = null;
List<Map> selfGoods = null;
try {
StringBuffer buff = new StringBuffer();
ioGoods = billingService.billingIOGoodsMessage();
BillExporterUtils.billExport(buff, ioGoods);
selfGoods = billingService.billingSelfGoodMessage();
BillExporterUtils.billExport(buff, selfGoods);
file = new File(buildFileName());
textFileWriter = new TextFileWriter(file, false);
textFileWriter.outPut(buff.toString());
buff = null;
return true;
} catch (Exception e) {
String resultLog = "未能成功从数据库中查询自用物资、备案清单进出单号信息,当前系统日期为:"
+ CalendarUtils.formatDate(new Date());
logger.error(resultLog, e);
} finally {
try {
if (textFileWriter != null) {
textFileWriter.closeFile();
textFileWriter = null;
}
if (ioGoods != null) {
ioGoods = null;
}
if (selfGoods != null) {
selfGoods = null;
}
System.gc();
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。