最近在学校做了个项目。类似于评教。本身项目问题不大,也没有什么难点、但是在做后台数据整理显示的时候出了一点小问题。
有一个功能,是遍历所有老师所有课程,然后求总的平均分再排序。测试的时候功能是实现了,但多点击几次之后。堆内存溢出了
上网百度了两天,查了点资料,用JDK自带的工具查看了一下内存的使用情况,发现每点击一次,Tenured Gen内存池的占用空间会增长几十M。而且运行gc还没有什么效果。网上资料说这个Tenured Gen内存池里面都是引用多次的变量(好像默认是31次以上)。用jmap导出内存情况查看了一下,没有特别突出的内存占用情况。总共占用150M内存,前十项能占到90多M,内存占用最高的[B和[C类型,看资料上说这是byte数组和char数组。
num #instances #bytes class name
----------------------------------------------
1: 8279 28828864 [B
2: 325408 20504992 [C
3: 465540 11172960 java.util.HashMap$Entry
4: 92373 9691352 [Ljava.util.HashMap$Entry;
5: 335598 8054352 java.lang.String
6: 215883 5181192 java.util.Hashtable$Entry
7: 308830 4941280 java.lang.Integer
8: 240621 4828536 [Ljava.lang.String;
9: 74366 4759424 com.mysql.jdbc.ConnectionPropertiesImpl$BooleanConnectionProperty
10: 32104 4180296 <constMethodKlass>
可是我项目里面只有一个字段是拆出来用byte数组判断的(20道选择题,每道题的选项)功能实现在下面
//做了一个缓存判断,如果有数据了就不在重新生成。
Object old_result = request.getSession().getAttribute("result");
if(old_result != null){
response.sendRedirect(request.getContextPath()+"/jsp/admin/display_sorted_all_course.jsp");
return null;
}
CiDAO cd = new CiDAO();
TiDAO td = new TiDAO();
List<Ti> lt = td.getAllTi();
Iterator<Ti> it_lt = lt.iterator();
//建立存储信息的数据结构,使用哈希表,以Tname为key,确定一个老师一条纪录
Hashtable<String, SortByTotalGrade> ht_t = new Hashtable<String, SortByTotalGrade>();
Ti ti = null;
Ci ci = null;
while(it_lt.hasNext()){
//取出一条Ti纪录,即一个老师的一门课程
ti = it_lt.next();
//如果是别的院系的老师,则不参加排名
if(ti.getTname().startsWith("@")){
continue;
}
//取出这个课程的所有评价信息
List<Ci> cl = cd.selectCi(ti.getCname(), ti.getSid());
if(cl == null){
//如果没有评价信息就跳过
continue;
}
Iterator<Ci> it_ci = cl.iterator();
int grade = 0;
byte[] info = null;
//遍历每条评价信息,算出总分
while(it_ci.hasNext()){
ci = it_ci.next();
info = ci.getInfo().getBytes();
for(int i = 0; i < 20; i++){
switch(info[i]){
case 'A':
case 'a':grade += 5;break;
case 'B':
case 'b':grade += 3;break;
case 'C':
case 'c':grade += 1;break;
}
}
info = null;
}
SortByTotalGrade sbtg = null;
if(ht_t.containsKey(ti.getTname())){
sbtg = ht_t.get(ti.getTname());
}else{
sbtg = new SortByTotalGrade(ti.getTname());
}
sbtg.addResult(cl.size(), grade);
cl = null;
ht_t.put(ti.getTname(), sbtg);
sbtg = null;
}
it_lt = null;
lt = null;
Set<String> ks = ht_t.keySet();
Iterator<String> it_ks = ks.iterator();
SortByTotalGrade[] result = new SortByTotalGrade[ks.size()];
int i = 0;
SortByTotalGrade sbtg = null;
String key = null;
while(it_ks.hasNext()){
key = it_ks.next();
sbtg = ht_t.get(key);
result[i] = sbtg;
i++;
}
ks = null;
ht_t = null;
Arrays.sort(result);
request.getSession().setAttribute("result", result);
return null;
怎么想也想不出来为什么、疑惑啊、
有一个功能,是遍历所有老师所有课程,然后求总的平均分再排序。测试的时候功能是实现了,但多点击几次之后。堆内存溢出了
上网百度了两天,查了点资料,用JDK自带的工具查看了一下内存的使用情况,发现每点击一次,Tenured Gen内存池的占用空间会增长几十M。而且运行gc还没有什么效果。网上资料说这个Tenured Gen内存池里面都是引用多次的变量(好像默认是31次以上)。用jmap导出内存情况查看了一下,没有特别突出的内存占用情况。总共占用150M内存,前十项能占到90多M,内存占用最高的[B和[C类型,看资料上说这是byte数组和char数组。
num #instances #bytes class name
----------------------------------------------
1: 8279 28828864 [B
2: 325408 20504992 [C
3: 465540 11172960 java.util.HashMap$Entry
4: 92373 9691352 [Ljava.util.HashMap$Entry;
5: 335598 8054352 java.lang.String
6: 215883 5181192 java.util.Hashtable$Entry
7: 308830 4941280 java.lang.Integer
8: 240621 4828536 [Ljava.lang.String;
9: 74366 4759424 com.mysql.jdbc.ConnectionPropertiesImpl$BooleanConnectionProperty
10: 32104 4180296 <constMethodKlass>
可是我项目里面只有一个字段是拆出来用byte数组判断的(20道选择题,每道题的选项)功能实现在下面
//做了一个缓存判断,如果有数据了就不在重新生成。
Object old_result = request.getSession().getAttribute("result");
if(old_result != null){
response.sendRedirect(request.getContextPath()+"/jsp/admin/display_sorted_all_course.jsp");
return null;
}
CiDAO cd = new CiDAO();
TiDAO td = new TiDAO();
List<Ti> lt = td.getAllTi();
Iterator<Ti> it_lt = lt.iterator();
//建立存储信息的数据结构,使用哈希表,以Tname为key,确定一个老师一条纪录
Hashtable<String, SortByTotalGrade> ht_t = new Hashtable<String, SortByTotalGrade>();
Ti ti = null;
Ci ci = null;
while(it_lt.hasNext()){
//取出一条Ti纪录,即一个老师的一门课程
ti = it_lt.next();
//如果是别的院系的老师,则不参加排名
if(ti.getTname().startsWith("@")){
continue;
}
//取出这个课程的所有评价信息
List<Ci> cl = cd.selectCi(ti.getCname(), ti.getSid());
if(cl == null){
//如果没有评价信息就跳过
continue;
}
Iterator<Ci> it_ci = cl.iterator();
int grade = 0;
byte[] info = null;
//遍历每条评价信息,算出总分
while(it_ci.hasNext()){
ci = it_ci.next();
info = ci.getInfo().getBytes();
for(int i = 0; i < 20; i++){
switch(info[i]){
case 'A':
case 'a':grade += 5;break;
case 'B':
case 'b':grade += 3;break;
case 'C':
case 'c':grade += 1;break;
}
}
info = null;
}
SortByTotalGrade sbtg = null;
if(ht_t.containsKey(ti.getTname())){
sbtg = ht_t.get(ti.getTname());
}else{
sbtg = new SortByTotalGrade(ti.getTname());
}
sbtg.addResult(cl.size(), grade);
cl = null;
ht_t.put(ti.getTname(), sbtg);
sbtg = null;
}
it_lt = null;
lt = null;
Set<String> ks = ht_t.keySet();
Iterator<String> it_ks = ks.iterator();
SortByTotalGrade[] result = new SortByTotalGrade[ks.size()];
int i = 0;
SortByTotalGrade sbtg = null;
String key = null;
while(it_ks.hasNext()){
key = it_ks.next();
sbtg = ht_t.get(key);
result[i] = sbtg;
i++;
}
ks = null;
ht_t = null;
Arrays.sort(result);
request.getSession().setAttribute("result", result);
return null;
怎么想也想不出来为什么、疑惑啊、
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货