您好我有一个java程序,可以使用JDBC同时访问远程数据库和本地数据库。
但是我得到了这个例外: - >线程“Thread-1964”中的异常java.lang.OutOfMemoryError:Java堆空间
现在我想使用任何分析工具,我可以在我的代码中找到这个异常的确切原因。
这是我的java程序
public class DBTestCases{
Connection localConnection;
Connection remoteConnection;
Connection localCon;
Connection remoteCon;
List<Connection> connectionsList;
String driver = "com.mysql.jdbc.Driver";
String user = "root";
String password = "root";
String dbName = "myDB";
String connectionUrl1= "jdbc:mysql://11.232.33:3306/"+dbName+"?user="+user+"&password="+password+"&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&maxReconnects=10";
String connectionUrl2= "jdbc:mysql://localhost:3306/"+dbName+"?user="+user+"&password="+password+"&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&maxReconnects=10";
public List<Connection> createConnection() {
try {
Class.forName(driver);
localCon = DriverManager.getConnection(connectionUrl2);
if(localCon != null)
System.out.println("connected to remote database at : "+new Date());
remoteCon = DriverManager.getConnection(connectionUrl1);
if(remoteCon != null)
System.out.println("connected to local database at : "+new Date());
connectionsList = new ArrayList<Connection>( 2 );
connectionsList.add( 0 , localCon );
connectionsList.add( 1 , remoteCon );
} catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
} catch(SQLException sqle) {
sqle.printStackTrace();
}
return connectionsList;
}
public void insert(){
Runnable runnable = new Runnable(){
public void run() {
PreparedStatement ps1 = null;
PreparedStatement ps2 = null;
String sql = "insert into user1(name, address, created_date)" +
" values('johnsan', 'usa', '2013-08-04')";
if(remoteConnection != null&&localConnection != null) {
System.out.println("Database Connection Is Established");
try {
ps1 = remoteConnection.prepareStatement(sql);
ps2 = localConnection.prepareStatement(sql);
int i = ps1.executeUpdate();
int k = ps2.executeUpdate();
if(i > 0) {
System.out.println("Data Inserted into remote database table Successfully");
}
if(k > 0) {
System.out.println("Data Inserted into local database table Successfully");
}
} catch (SQLException s) {
System.out.println("SQL code does not execute.");
s.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Inserting values in db");
}
};
Thread thread = new Thread(runnable);
thread.start();
}
public void retrieve(){
Runnable runnable = new Runnable(){
public void run() {
try {
Statement st1 = localConnection.createStatement();
Statement st2 = remoteConnection.createStatement();
ResultSet res1 = st1.executeQuery("SELECT * FROM user1");
ResultSet res2 = st2.executeQuery("SELECT * FROM user1");
System.out.println("---------------------------Local Database------------------------");
while (res1.next()) {
Long i = res1.getLong("userId");
String s1 = res1.getString("name");
String s2 = res1.getString("address");
java.sql.Date d = res1.getDate("created_date");
System.out.println(i + "\t\t" + s1 + "\t\t" + s2 + "\t\t"+ d);
}
System.out.println("------------------------Remote Database---------------------");
while (res2.next()) {
Long i = res2.getLong("userId");
String s1 = res2.getString("name");
String s2 = res2.getString("address");
java.sql.Date d = res2.getDate("created_date");
System.out.println(i + "\t\t" + s1 + "\t\t" + s2 + "\t\t"+ d);
}
} catch (SQLException s) {
System.out.println("SQL code does not execute.");
s.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
public static void main(String[] args) {
DBTestCases dbTestCases = new DBTestCases();
List l = dbTestCases.createConnection();
dbTestCases.localConnection = (Connection)l.get(0);
dbTestCases.remoteConnection = (Connection)l.get(1);
for(;;) {
dbTestCases.insert();
dbTestCases.countRows();
dbTestCases.retrieve();
}
}
}
任何人都可以帮助我,这是最好的工具,我必须使用它,以及任何链接。我正在使用Linux操作系统。
我想我正在为每个方法调用启动一个新线程,任何人都可以建议如何在再次启动之前关闭线程或使用thred池..
提前谢谢你。
答案 0 :(得分:0)
同样的问题曾经发生在我身上。问题是你的java保留堆内存。这个堆内存可以通过一个java配置文件进行配置;它的最小和最大金额。
答案 1 :(得分:0)
有很多个人资料。 我一直在使用Visual VM一段时间,至少对我有用。它易于使用,也是非常强大的工具。 这是链接: http://visualvm.java.net
不确定您使用的是哪个IDE。但是OutOfMemoryError没有任何关系,这意味着它是一个RuntimeException。
答案 2 :(得分:0)
一点点offtopic(因为我不打算建议你一个探查器),但我认为问题来自这些线
ps1 = remoteConnection.prepareStatement(sql);
ps2 = localConnection.prepareStatement(sql);
int i = ps1.executeUpdate();
int k = ps2.executeUpdate();
和
Statement st1 = localConnection.createStatement();
Statement st2 = remoteConnection.createStatement();
ResultSet res1 = st1.executeQuery("SELECT * FROM user1");
ResultSet res2 = st2.executeQuery("SELECT * FROM user1");
创建PreparedStatement并使用它之后,应该关闭它。要么在不再需要时使用close()方法,要么使用try-with-resources(它会自动使用close())。 Java Tutorial on statements和try-with-resources。另请考虑阅读this和this主题。
A会像这样重写你的代码(实际上没有尝试过,但它编译并且它应该消除内存泄漏问题):
public class DBTestCases {
Connection localConnection;
Connection remoteConnection;
Connection localCon;
Connection remoteCon;
List<Connection> connectionsList;
String driver = "com.mysql.jdbc.Driver";
String user = "root";
String password = "root";
String dbName = "myDB";
String connectionUrl1= "jdbc:mysql://11.232.33:3306/"+dbName+"?user="+user+"&password="+password+"&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&maxReconnects=10";
String connectionUrl2= "jdbc:mysql://localhost:3306/"+dbName+"?user="+user+"&password="+password+"&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&maxReconnects=10";
public List<Connection> createConnection() {
try {
Class.forName(driver);
localCon = DriverManager.getConnection(connectionUrl2);
if(localCon != null)
System.out.println("connected to remote database at : "+new Date());
remoteCon = DriverManager.getConnection(connectionUrl1);
if(remoteCon != null)
System.out.println("connected to local database at : "+new Date());
connectionsList = new ArrayList<Connection>( 2 );
connectionsList.add( 0 , localCon );
connectionsList.add( 1 , remoteCon );
} catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
} catch(SQLException sqle) {
sqle.printStackTrace();
}
return connectionsList;
}
public void insert(){
Runnable runnable = new Runnable(){
public void run() {
PreparedStatement ps1 = null;
PreparedStatement ps2 = null;
String sql = "insert into user1(name, address, created_date)" +
" values('johnsan', 'usa', '2013-08-04')";
if(remoteConnection != null&&localConnection != null) {
System.out.println("Database Connection Is Established");
try {
ps1 = remoteConnection.prepareStatement(sql);
ps2 = localConnection.prepareStatement(sql);
int i = ps1.executeUpdate();
int k = ps2.executeUpdate();
if(i > 0) {
System.out.println("Data Inserted into remote database table Successfully");
}
if(k > 0) {
System.out.println("Data Inserted into local database table Successfully");
}
} catch (SQLException s) {
System.out.println("SQL code does not execute.");
s.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
} finally {
if (ps1 != null) {
try {
ps1.close();
} catch (SQLException ex) {
System.out.println("Cannot close ps1 statement.");
}
}
if (ps2 != null) {
try {
ps2.close();
} catch (SQLException ex) {
System.out.println("Cannot close ps2 statement.");
}
}
}
}
System.out.println("Inserting values in db");
}
};
Thread thread = new Thread(runnable);
thread.start();
}
public void retrieve(){
Runnable runnable = new Runnable(){
public void run() {
Statement st1 = null;
Statement st2 = null;
ResultSet res1 = null;
ResultSet res2 = null;
try {
st1 = localConnection.createStatement();
st2 = remoteConnection.createStatement();
res1 = st1.executeQuery("SELECT * FROM user1");
res2 = st2.executeQuery("SELECT * FROM user1");
System.out.println("---------------------------Local Database------------------------");
while (res1.next()) {
Long i = res1.getLong("userId");
String s1 = res1.getString("name");
String s2 = res1.getString("address");
java.sql.Date d = res1.getDate("created_date");
System.out.println(i + "\t\t" + s1 + "\t\t" + s2 + "\t\t"+ d);
}
System.out.println("------------------------Remote Database---------------------");
while (res2.next()) {
Long i = res2.getLong("userId");
String s1 = res2.getString("name");
String s2 = res2.getString("address");
java.sql.Date d = res2.getDate("created_date");
System.out.println(i + "\t\t" + s1 + "\t\t" + s2 + "\t\t"+ d);
}
} catch (SQLException s) {
System.out.println("SQL code does not execute.");
s.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
} finally {
if (res1 != null) {
try {
res1.close();
} catch (SQLException ex) {
System.out.println("Cannot close res1 result set.");
}
}
if (st1 != null) {
try {
st1.close();
} catch (SQLException ex) {
System.out.println("Cannot close st1 statement.");
ex.printStackTrace();
}
}
if (res2 != null) {
try {
res2.close();
} catch (SQLException ex) {
System.out.println("Cannot close res2 result set.");
}
}
if (st2 != null) {
try {
st2.close();
} catch (SQLException ex) {
System.out.println("Cannot close st2 statement.");
ex.printStackTrace();
}
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
public static void main(String[] args) {
DBTestCases dbTestCases = new DBTestCases();
List l = dbTestCases.createConnection();
dbTestCases.localConnection = (Connection)l.get(0);
dbTestCases.remoteConnection = (Connection)l.get(1);
for(;;) {
dbTestCases.insert();
dbTestCases.countRows();
dbTestCases.retrieve();
}
}
}
这些陈述还有另一个问题:
ResultSet res1 = st1.executeQuery("SELECT * FROM user1");
ResultSet res2 = st2.executeQuery("SELECT * FROM user1");
我绝不应该(极少数情况下)在不使用WHERE
条件的情况下读取整个表格。此外,如果您只需要一列created_date
,那么您必须像这样重写它:
ResultSet res1 = st1.executeQuery("SELECT created_date FROM user1");
ResultSet res2 = st2.executeQuery("SELECT created_date FROM user1");
但我并没有在完整列表中替换它,因为它可能只是“快速而肮脏”的代码。 :)