在開發的期間
系統在運行的時候出現了一些問題
現將我的問題解決方法做一個小結
供以後作項目的參考
並請大家不吝指教
問題 Resin 的數據庫連接數目在程序運行中不斷增長
最後連接數目超過最大數
導致Resin服務關閉
原因
在操作完數據庫後
沒有關閉數據庫連接
或者是返回結果集(Resultset)
而無法在jsp中關閉數據庫連接
解決方法
. 在操作完數據庫要關閉數據庫連接
. 盡量不要返回結果集Resultset
可以返回Vector(一個字段)
Hashtable(多個字段)
這樣可以在javabean中關閉數據庫
. 如果javabean中返回的是結果集(Resultset)
也可以在javaBean中寫一個connectDB(連接數據庫)
closeDB(關閉數據庫)的方法
然後jsp裡面調用connectDB()
建立數據庫連接
同時就可以對數據庫進行操作了
操作數據庫完畢
可以通過closeDB() 來關閉數據庫
關閉連接時盡量使用conn
close()
rs
close()
而不要另外寫方法去關閉它
如調用DB
closeConnection(conn)等等
這樣其實對性能有一定影響
因為該性能經過了我對單個文件的測試
關閉連接時請按順序進行
如rs
close()
stmt
close()nn
close()
問題 在運行某一個jsp 程序的時候
Resin 的內存陡然增長
而且居高不下
最終導致Resin 內存不足
甚至當機
原因
過度使用內存
解決方法
. 由於數據量比較大
在對字符串進行操作的時候
使用 + 進行字符串連接
而
相信大家對String都非常熟悉
我們也經常要用它來做字符串的連接什麼的
例如
String a =b+c file://b
c 都是String
但是在實際的編譯中卻是這樣
String a=new StringBuffer()
append(b)
append(c)
toString() 顯然
在一個簡單的語句中卻意外的多生成了
個對象
StringBuffer()
toString返回的一個String
我們比較一下這兩段程序的性能
程序片斷一
StringBuffer s=new StringBuffer();
long start = System
currentTimeMillis();
for (int i=
;i<
;i++){
s
+=
a
;
}
long stop = System
currentTimeMillis();
System
out
println(stop
start);
程序片斷二
StringBuffer s=new StringBuffer(
);//
long start=System
currentTimeMillis();
for (int i=
;i<
;i++){
s
append(
a
);
}
long stop=System
currentTimeMillis();
System
out
println(stop
start);
比較一下結果
差距很明顯
至於為什麼String的連接這麼做
因為String無法直接改變其長度
而必須采用StringBuffer的用法
因此建議使用StringBuffer 的append 方法來進行字符串相連
.在解決這個問題的時候
我也嘗試使用上面的方法
效果並不是很明顯(消耗內存上)
後來在顯示大量數據的時候
避免字符串相連的步驟
而直接使用out
println()
直接輸出
問題
Java並不阻止程序占用過多的內存
當對象向堆所請求的內存不足時
垃圾收集器(Garbage Collector)就會自動啟動
釋放那些引用數為零的對象所占用的內存
Java也不會自動釋放無用的對象的引用
如果程序忘記釋放指向對象的引用
則程序運行時的內存隨著時間的推移而增加
發生所謂內存洩漏(memory leaks)
創建對象不但消耗CPU的時間和內存
同時
為釋放對象內存JVM需不停地啟動垃圾收集器(Garbage Collector)
這也會消耗大量的CPU時間
解決方法
由於在運行一段時間jsp程序後
Resin 的內存會有一個緩慢的增長
這樣也會導致內存溢出
為了避免這總現象的出現
最終的解決方法是
編寫一個servlet程序
在啟動服務器的時候
啟動一個這個servlet
每隔
分鐘運行在服務器端運行一次
來定時回收內存
問題 log文件裡面的調試信息沒有注釋去掉
解決方法
在程序通過後
盡量把調試的信息注釋去掉
同時在捕捉錯誤的時候要寫明程序名稱
方便查找
問題 改善性能
提高速度
具體實例
我們再來看一個有關Vector類的代碼片段
for(int I=
; I<v
size(); I++) { System
out
println( v
get(I)
getClass()
toString()); }
如果v包含
個元素
這個代碼片段將調用v
size()方法
次
雖然size方法是一個簡單的方法
但它仍舊需要一次方法調用的開銷
至少JVM需要為它配置以及清除堆棧環境
在這裡
for循環內部的代碼不會以任何方式修改Vector類型對象v的大小
因此上面的代碼最好改寫成下面這種形式
int size = v
size(); for(int I=
; I<size; I++) { System
out
println( v
get(I)
getClass()
toString()); }
雖然這是一個簡單的改動
但它仍舊贏得了性能
畢竟
每一個CPU周期都是寶貴的
問題 在 jsp 文件裡面 不要寫 <%@ page import=
java
lang
*
%>
因為java 不需要引入此包就可以引用裡面的類文件
問題 使用vector+hashtable 一次返回查詢結果resulset
解決方法
記錄集
將一條記錄放到一個hashtable裡面
然後把它再
添加到vector裡面
循環記錄下結果集
返回vector
具體見後面的java文件的部分代碼(不包擴數據庫的連接和關閉)
package pany;
/********************************************
***** 說明
***** 記錄集
一條記錄用放到一個hashtable裡面
然後把它再
放到vector裡面
循環記錄下結果集
返回vector
*********************************************/
import java
io
*;
import java
sql
*;
import java
util
*;
import java
text
*;
public class hashtable_vector_rs
{
/*
*/
/* 函數名稱
getMultiRowInfo
/* 功能描述
返回記錄集
放到Hashtable裡面
/* 參數
sql 語句
字段個數
/* 返回值: 成功
htable
失敗
null
/*
*/
public Vector ListResult(String sqlStatement
int num)
{
Vector ListRs=new Vector();
try
{
connectDB();
rs=stmt
executeQuery(sqlStatement);
//判斷字段數據類型
//date型 返回
//int型 返回
//bigint型 返回
//String型 返回
//(char 型)返回
int t =
;
rsmd = rs
getMetaData();
int ColumnCount=
;
if(num>
)
ColumnCount = num;
else
ColumnCount = rsmd
getColumnCount();
while(rs
next())
{
Hashtable htable =new Hashtable();
for (int i =
; i <= ColumnCount; i++)
{
t=rsmd
getColumnType(i);
System
out
println(
i=
+i+
t=
+t+
name=
+rsmd
getColumnName(i));
if(t==
||t==
||t==
)
{
if(rs
getString(i)==null|| rs
getString(i)
equals(
))
htable
put(rsmd
getColumnName(i)
);
else
htable
put(rsmd
getColumnName(i)
rs
getString(i));
}
else if(t==
)
{
htable
put(rsmd
getColumnName(i)
rs
getDate(i)
toString());
}
else if(t==
||t==
)
{
htable
put(rsmd
getColumnName(i)
Integer
toString(rs
getInt(i)));
}
}
ListRs
add(htable);
}//e
return ListRs;
}
catch(Exception listError)
{
System
out
println(
數據庫操作失敗!
+listError);
return null;
}
finally
{
try
{
closeDB();
}
catch(Exception closeErr)
{
System
out
println(
關閉數據庫出錯
+closeErr);
}
}
}
}
問題: jsp的程序也有設計的不夠合理的地方
例如
選擇一個下拉框
提交一次
列出所選的數據
選擇另外一個下拉框再次提交
再次列出所選的數據
解決方法
盡量一次把條件選擇完畢
然後列出所選擇的數據
並且在數據多的時候
盡量使用翻頁
減少運行時間
問題 性能優化
盡量使用PreparedStatement
解決方法
PreparedStatement 對象和使用的普通的 Statement 對象有兩點不同
第一
它們是為了性能更快而由 JDBC 驅動程序或數據庫編譯(預編譯)的
第二
它們接受一個或多個動態輸入參數
稱為 IN 參數
這兩點讓 PreparedStatement 對象適用於重復的 SQL 操作
其中操作基本上都是一樣的
只有微小的差異(如數據載入)
要讓 SQL 語句在使用前預備好
在 PreparedStatement 對象創建時必須將 SQL 傳送到 JDBC 驅動程序
而不是在其執行時才傳送
IN 參數用 SQL String 中的 ? 占位符表示
在 PreparedStatement 能夠成功地執行前
還必須調用 PreparedStatement 對象的 se
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27504.html