最近在处理jvm内存问题,对jsp数据库操作的内存处理不很清楚,请各位给出意见,最好能有实际的测试依据。一、基本使用
db_test.jsp:
<%
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = getConnection( ); //此处省略获取connection的具体代码
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from tab_a");
if ( rs.next() ) out.println(rs.getString(1));
}
catch(SQLException ex) {
}
finally{
if ( rs != null ) { rs.close(); rs = null; }
if ( stmt != null ) { stmt.close(); stmt = null; }
if ( conn != null ) { conn.close(); conn = null; }
}
%>
想请问:如果以上代码没有问题的运行完毕,是不是rs,stmt,conn所占用的java虚拟机内存都能被回收呢?
被close()但不是null状态的rs会不会占用内存不能释放呢?
比如finally中只执行rs.close(),stmt.close(),conn.close(),而省略s=null,stmt=null,conn=null,这两种有什么本质的不同呢?
也就是说rs=null等这些语句有什么明确的作用或者好处呢?
不加上这些赋空语句又有哪些坏处呢?
db_test.jsp:
<%
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = getConnection( ); //此处省略获取connection的具体代码
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from tab_a");
if ( rs.next() ) out.println(rs.getString(1));
}
catch(SQLException ex) {
}
finally{
if ( rs != null ) { rs.close(); rs = null; }
if ( stmt != null ) { stmt.close(); stmt = null; }
if ( conn != null ) { conn.close(); conn = null; }
}
%>
想请问:如果以上代码没有问题的运行完毕,是不是rs,stmt,conn所占用的java虚拟机内存都能被回收呢?
被close()但不是null状态的rs会不会占用内存不能释放呢?
比如finally中只执行rs.close(),stmt.close(),conn.close(),而省略s=null,stmt=null,conn=null,这两种有什么本质的不同呢?
也就是说rs=null等这些语句有什么明确的作用或者好处呢?
不加上这些赋空语句又有哪些坏处呢?
解决方案 »
- 求助:关于HTTP Status 404 - /Test/ The requested resource () is not available.的问题
- 谁能教我一下java开发调用ImageMagick的知识?在线等。多谢
- Java Web 开发中海量数据高并发访问
- 关于jfreechart柱状图显示的两个问题
- 为什么最简单的JSP都看不了...菜鸟问题.
- 关于网站地图的问题
- 关于oracle.sql.CLOB的问题,解决后一定给分,在线等待!
- 郁闷~~请教JSP————中文问题
- uploadify上传图片后 使用struts如何返回值给jsp页面呢?
- json转map 怎么转
- 单选框和复选框同时使用的问题?
- 菜鸟问题。怎么样把日期转化为毫秒数。然后在把毫秒数转化为日期。
......
rs = stmt.executeQuery("select * from tab_a");
if ( rs.next() ) out.println(rs.getString(1));
rs = stmt.executeQuery("select * from tab_b");
if ( rs.next() ) out.println(rs.getString(1));
rs = stmt.executeQuery("select * from tab_c");
if ( rs.next() ) out.println(rs.getString(1));
......
//执行finally块
如上一个rs多次利用后最后才进行close()操作,这三次的executeQuery操作中java是怎样使用内存的呢?
假定第一次query操作需要占用10k内存,第二次query操作需要占用15k内存,那java是在第一次10k基础上再扩展5k内存还是丢弃原来的10K内存而重新申请15k内存呢?如果第三次query只需要2k内存的话,java会将占用的15k自动压缩为2k还是另开辟2k内存呢?
最终java会消耗多少内存而最好能回收多少内存呢? ......
rs = stmt.executeQuery("select * from tab_a");
if ( rs.next() ) out.println(rs.getString(1));
rs.close(); rs = stmt.executeQuery("select * from tab_b");
if ( rs.next() ) out.println(rs.getString(1));
rs.close();
rs = stmt.executeQuery("select * from tab_c");
if ( rs.next() ) out.println(rs.getString(1));
rs.close();
......
//执行finally块
每执行一次Query之后就执行一次rs.close(),与上面的做法有哪些不同呢?
java是怎样处理内存的呢?
//javabean
public class db {
private Connection conn;
private Statement stmt;
private ResultSet rs; public void initdb() {
....
}
public ResultSet ExecSelect(String sql) {
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
return rs;
}
public void closedb() {
if ( rs != null ) { rs.close(); rs = null; }
if ( stmt != null ) { stmt.close(); stmt = null; }
if ( conn != null ) { conn.close(); conn = null; }
}
//jsp:A
<jsp:useBean id="db" scope="page" class="db"/> ResultSet rs_jsp = null; rs_jsp = db.ExecSelect("select * from tab_a");
rs_jsp.next();
rs_jsp = db.ExecSelect("select * from tab_b");
rs_jsp.next(); db.closedb();
如上所示,db.closedb()能否将rs_jsp,db.rs全部close呢? 如果可以close的话,db.rs为null,而rs_jsp应该还不是null吧?
如果rs_jsp不为null,那么java如何处理内存呢? //jsp:B (两次select操作按顺序处理的。处理tab_b时,tab_a中的数据已经不需要了)
<jsp:useBean id="db" scope="page" class="db"/>
ResultSet rs_jsp = null; rs_jsp = db.ExecSelect("select * from tab_a");
rs_jsp.next();
rs_jsp = db.ExecSelect("select * from tab_b");
rs_jsp.next(); rs_jsp.close(); //这两句话有没有必要加上呢?
rs_jsp = null; //这两句话有没有必要加上呢? db.closedb();
与jsp:A相比,jsp_B的代码有什么作用呢?//jsp:C(两次select操作是共存处理的。只有等tab_b处理完毕,tab_a中的数据才能关闭)
<jsp:useBean id="db" scope="page" class="db"/> ResultSet rs_jsp_a = null;
ResultSet rs_jsp_b = null; rs_jsp_a = db.ExecSelect("select * from tab_a");
rs_jsp_a.next();
rs_jsp_b = db.ExecSelect("select * from tab_b");
rs_jsp_b.next(); rs_jsp_a.close(); //这两句话有没有必要加上呢?
rs_jsp_a = null; //这两句话有没有必要加上呢?
rs_jsp_b.close(); //这两句话有没有必要加上呢?
rs_jsp_b = null; //这两句话有没有必要加上呢? db.closedb();
想请问,在这个运行过程中,rs_jsp_a、rs_jsp_b、db.rs这三者是怎样的联系关系呢? java是怎样安排内存并回收内存的呢?
这种实现方法会不会存在内存泄漏呢?
ResultSet rs;只是定义一个对象, 当 stmt.executeQuery("select * from tab_a");就生成了一个新的对象, 每个对象都要关闭, 因此, 在rs变量给另外使用前, 原来的对象需要关闭.关键: java一切都是对象
1.
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = getConnection( ); //此处省略获取connection的具体代码
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from tab_a");
if ( rs.next() ) out.println(rs.getString(1));
}
catch(SQLException ex) {
}
finally{
if ( rs != null ) { rs.close(); rs = null; }
if ( stmt != null ) { stmt.close(); stmt = null; }
if ( conn != null ) { conn.close(); conn = null; }
}2.
rs = stmt.executeQuery("select * from tab_a");
if ( rs.next() ) out.println(rs.getString(1));
rs.close(); rs = stmt.executeQuery("select * from tab_b");
if ( rs.next() ) out.println(rs.getString(1));
rs.close();
rs = stmt.executeQuery("select * from tab_c");
if ( rs.next() ) out.println(rs.getString(1));
rs.close(); 3.
rs_jsp_a.close(); //这两句话有必要加上
rs_jsp_a = null; //这两句话有必要加上
rs_jsp_b.close(); //这两句话有必要加上
rs_jsp_b = null; //这两句话有必要加上
请问Jimmy,terry_yip
2.
rs = stmt.executeQuery("select * from tab_a");
if ( rs.next() ) out.println(rs.getString(1));
rs.close(); rs = stmt.executeQuery("select * from tab_b");
if ( rs.next() ) out.println(rs.getString(1));
rs.close();
rs = stmt.executeQuery("select * from tab_c");
if ( rs.next() ) out.println(rs.getString(1));
rs.close();
那应该是申请了三次内存吧?请看下面的问题:
第1次,rs指向select * from tab_a的内存区,简称mem_a ,rs.close()后关闭该内存块,虽然可以被回收,但由于rs不等于null,rs指针仍指向该内存区域,所以被垃圾回收的优先级别不高。
第2次,rs指向select * from tab_b的内存区,简称mem_b ,此时rs指针是不是从mem_a移动到mem_b,而mem_a成为没有被引用的完全close的内存块从而具备了较高被回收的优先级别呢?
而rs.close()之后,mem_b成为被关闭的但是被rs引用的内存块,可被垃圾回收但优先级不高?
第3次,rs指向select * from tab_c的内存区,简称mem_c,此时rs指针移动到mem_c,mem_b成为没有被引用的完全close的内存块从而具备了较高被回收的优先级别呢? 如此循环反复??
rs = stmt.executeQuery("select * from tab_a");
if ( rs.next() ) out.println(rs.getString(1));
//rs.close(); rs = stmt.executeQuery("select * from tab_b");
if ( rs.next() ) out.println(rs.getString(1));
//rs.close();
rs = stmt.executeQuery("select * from tab_c");
if ( rs.next() ) out.println(rs.getString(1));
rs.close();
那是不是前两次的内存没有被关闭而不能被回收造成内存泄漏啊?
最后:jsp里面这样写是结构很垃圾的,根本不会这么写。想这些连接和事务的管理完全可以写一个AOP动态植入
其次,有些资源必须在使用后被关闭,如数据库连接,文件,等等,垃圾回收是不会对此类资源回收的,这个一般会造成内存泄漏。但是如果关闭后,就可以被正常回收,是否设置为null其实并无关紧要,只是加快了垃圾回收的运行速度。
最后,程序没有办法控制内存被垃圾回收的优先级
rs = stmt.executeQuery("select * from tab_a");
if ( rs.next() ) out.println(rs.getString(1));
//rs.close();
rs = stmt.executeQuery("select * from tab_b");
if ( rs.next() ) out.println(rs.getString(1));
//rs.close();
rs = stmt.executeQuery("select * from tab_c");
if ( rs.next() ) out.println(rs.getString(1));
这三次操作java是怎样使用内存的?rs.close()和rs=null对内存引用有什么影响?对内存资源高效回收(或者防止内存泄漏)到底应该处理更合适?