I am getting the "java.sql.SQLException: [SQLITE_MISUSE] Library used incorrectly (out of memory)". I paste the code sample for my database connection object
public class DBhandler {
private String DBUrl="d:\\sqlitedb\\somdb.db";
private String driverName="org.sqlite.JDBC";
private String jdbc="jdbc:sqlite:";
private Connection con=null;
private Statement stmnt=null;
public DBhandler()
{
try {
Class.forName(this.driverName);
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
this.con=DriverManager.getConnection(this.jdbc+this.DBUrl);
this.stmnt=con.createStatement();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public CurrentActiveSom getCurrentActiveSom()
{
CurrentActiveSom cas=null;
String query="select * from current_active_som where active=1";
ResultSet rs=null;
try {
rs=this.stmnt.executeQuery(query);
if (rs.next())
{
cas= new CurrentActiveSom();
cas.setMonth(rs.getString("month"));
cas.setYear(rs.getString("year"));
cas.setIsActive(rs.getInt("active"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try {
rs.close();
this.stmnt.close();
this.con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return cas;
}
public CurrentActiveSom getIsDoneSom(String month,String year)
{
CurrentActiveSom cas=null;
String query="select * from current_active_som where month='"+month+"' and year='"+year+"' and active=0";
ResultSet rs=null;
try {
rs=this.stmnt.executeQuery(query); //this is exception line
}
if (rs.next())
{
cas= new CurrentActiveSom();
cas.setMonth(rs.getString("month"));
cas.setYear(rs.getString("year"));
cas.setIsActive(rs.getInt("active"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try {
//rs.close(); //if i uncomment this gets null pointer exception
this.stmnt.close();
this.con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return cas;
}
The call to these Two methods with same object of DBhandler like
DBhandler db=new DBhandler();
CurrentActiveSom cas1=db.getCurrentActiveSom();
CurrentActiveSom cas2=db.getIsDoneSom(String month,String year)
then I am getting the above exception ,
but if we call thses 2 methods with different object DBhandler like
DBhandler db1=new DBhandler();
DBhandler db2=new DBhandler();
CurrentActiveSom cas1=db1.getCurrentActiveSom();
CurrentActiveSom cas2=db2.getIsDoneSom(String month,String year)
Then code is working fine.
Is this because of sync problem, with connection ? how to resolve this problem?
Well, the "out of memory"error looks weird, but one definitive error lies in creating Connection once per program run (in the constructor) and then closing it in each data access method.
This code:
CurrentActiveSom cas1=db.getCurrentActiveSom();
closes the Connection, so this code:
CurrentActiveSom cas2=db.getIsDoneSom(String month,String year)
tries to get data from a closed database. This is OK if you are using some kind of connection pooling in which closing a connection returns it to the pool. But it seems you're working on a single physical connection.
So just close it after you're done getting data from DB, and not in each data access method.
You close connection before you call `rs.next()so ResultSet try to read from connection, that has been already closed.
Related
I've searched for a long time for this in here and other places, and could not find my answer:
As part of a project I require to make a set of Connection objects (SQL Server) to take and restore connections to (Connection pool).
My issue is how to manipulate the objects in the set:
When a client requests a Connection I can remove it from the set, and when he's finished - add it back (since it's all unique values anyway).
But I am having trouble with this.
edit:
My code runs to an issue:
Exception in thread "Thread-10" java.util.ConcurrentModificationException
at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1597)
at java.base/java.util.HashMap$KeyIterator.next(HashMap.java:1620)
at connectionUtilities.ConnectionPool.getConnection(ConnectionPool.java:105)
at main.Main$1.run(Main.java:22)
at java.base/java.lang.Thread.run(Thread.java:833)
at line:
connection = (Connection)iterator.next();
I firstly use a constructor to add 10 connections to the set:
public ConnectionPool() {
for (int i = 0; i <= 9; i++) {
try {
Class.forName(jdbcDriver);
System.out.println("driver loaded succesfully");
connection = DriverManager.getConnection(connectionUrl);
connectionSet.add(connection);
System.out.println("connection created succesfully.");
System.out.println("Connection id: " + connectionSet.iterator());
System.out.println("connections Final size= " + connectionSet.size());
this.counter++;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(connectionSet);
// String[] conPoolArray = connectionSet.toArray(new
// String[connectionSet.size()]);
}
Here is my getConnection method (iterator is declared in the class as):
Iterator iterator = connectionSet.iterator();
public Connection getConnection() {
synchronized (instance) {
if (!connectionSet.isEmpty()) {
connection = (Connection)iterator.next();
return connection;
} else {
try {
instance.wait();
instance.getConnection();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return connection;
}
I am receiving the java.util.ConcurrentModificationException error and I understand it's because I can't adjust the set while iterating over it.
Any suggestions?
Thanks up front!
I have a problem with this method:
public void insertIntoQueue(DTOQueue dtoQueue) {
DbConnection dbConnection = new DbConnection();
Connection conn;
try {
conn = dbConnection.coneccion();
String sql = " INSERT INTO PURE_ENC_QUEUE (queueId,queueName) values(?,?);";
//creating PreparedStatement object to execute query
PreparedStatement preStatement = conn.prepareStatement(sql);
preStatement.setString(1, dtoQueue.getQueueId());
preStatement.setString(2, dtoQueue.getQueueName());
int result = preStatement.executeUpdate();
DbConnection.closeConnection(conn);
if(result > 0) {
System.out.println("Insertado");
} else {
System.out.println("No insertado");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("done");
}
When I run it, throws the exception
java.sql.SQLException: ORA-00933: SQL command not properly ended
Any idea about the problem? Thank you!
You need to remove the semicolon at the end of the query string, i.e.:
String sql = "INSERT INTO PURE_ENC_QUEUE (queueId,queueName) values(?,?)";
Also, it would be a good idea to refactor the code to use the try-with-resources statement.
I have few issues with my tomcat application.
I'm using a linux server with 1024M memory.
I deploy my app on the tomcat, and everything working great.
Recently i notice that the 'Tenured Gen' heap memory not free up when it should...
It reach 99% and then crash tomcat..
I check my application with VisualVM, and the same result.
it fill up the memory and the 'Old Gen' never free up.
This is when the application run few minutes with no request:
IMG: Everything looks normal
And when I start to send requests with 200 Thread on a loop
this what happened:
IMG: all memories are full
So then I check data on the MAT, and this is my result:
IMG: look like a memory leak
IMG: Problem with the sql jdbc?
IMG: Can't understand what is wrong
this is my ConnectionPool class:
public class ConnectionPool {
private static ConnectionPool singleton = null;
private ArrayList<Connection> freeConnections;
private ArrayList<Connection> allConnections;
private int MAX_CONNECTIONS = 1;
private final String shema = "Topic";
private final String url = "jdbc:mysql://localhost:3306/"+shema+"? autoReconnect=true&useSSL=false";
private final String username = "root";
private final String password = "password";
public static ConnectionPool getInstance(){
if (singleton == null)
{
synchronized (ConnectionPool.class) {
if (singleton == null){
System.out.println("ConnectionPool get instance");
try {
singleton = new ConnectionPool();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //this will invoke the constructor
}
}
}
return singleton;
}
private ConnectionPool() throws Exception {
freeConnections = new ArrayList<Connection>();
allConnections = new ArrayList<Connection>();
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < MAX_CONNECTIONS; i++) {
try {
addNewConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void addNewConnection() throws SQLException {
try {
Connection conn = DriverManager.getConnection(url, username, password);
freeConnections.add(conn);
allConnections.add(conn);
} catch (SQLException e) {
throw e;
}
}
public Connection getConnection()
{
while (true) {
synchronized (freeConnections) {
if (freeConnections.size() != 0) { // free connection is available
Connection conn = freeConnections.get(0);
freeConnections.remove(0);
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
try {
freeConnections.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void returnConnection(Connection conn)
{
if (null == conn) { // ignore invalid value
return;
}
if (!allConnections.contains(conn)) {
return;
}
synchronized (freeConnections) {
if (freeConnections.contains(conn)) {
return;
}
freeConnections.add(conn);
freeConnections.notifyAll();
return;
}
}
public void closeAllconnections()
{
for (Connection conn : allConnections) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
System.out.println("ConnectionPool all connection closed");
deregisterDriver();
}
public void deregisterDriver() {
try {
java.sql.Driver driver = DriverManager.getDriver(url);
DriverManager.deregisterDriver(driver);
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("ConnectionPool deregister driver");
}
}
Please help me to understand what is wrong and explain me.
1.Why the GC won't free up or why he can't do his job?
2.Is something wrong with my ConnectionPool Class?
3.why tomcat not saying anything about OutOfMemoryException in my logs(just crashing)?
See the connection details, apparently you have 10 connections and each retains cca 66 MB if the heap summing up to 660 MB required RAM.
I don't know what data you select, however when returning a connection you may want to close all resultsets and statements (why are you creating your own pool? dbcp, c3p0 or commons-pool ain't good enough? for learning?) and seems it may be not enough. I really don't know what the pool implementations do to release all resources properly.
And seems it is not so straightforward to share open connections between multiple threads Java MySQL JDBC Memory Leak so I would suggest to use a working pool solution (dbcp)
I'm trying to figure out how to rollback commits from multiple methods. I want to do something like the following (editing for brevity)
public void testMultipleMethodRollback() throws DatabaseException {
Connection conn = connect();
fakeMethodRollback1();
fakeMethodRollback2();
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
and currently all my methods are formatted like this
public void fakeMethodRollback1() throws DatabaseException {
Connection con = connect();
PreparedStatement ps = null;
ResultSet rs = null;
// insert some queries
try {
String query = "some query";
ps = conn.prepareStatement(query);
ps.executeUpdate(query);
query = "some query";
ps = conn.prepareStatement(query);
ps.executeUpdate(query);
con.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new DatabaseException(e);
} finally {
close(rs, ps, conn);
}
}
because I want to be able to use the other methods independently, how can I do a rollback where if one method fails, the others will roll back? I fear I have my whole class setup wrong or at least wrong enough that this can't be accomplished without major work. I can't change the methods to return a connection, because half of my methods are get methods, which are already returning other data. Any ideas?
I am building a database connection scanner for my security course at university. I have used DriverManager.getConnection(connectionURL, username, password) and it seems to work fine but with one exception that I just cannot understand. If I enter the wrong username it is still returning a connection??? my test code is pasted below. Any pointers would be much appreciated. It returns the correct error if I put the wrong password in, if I turn the server off it tells me. But for some unknown reason it will not tell me if the username is wrong, its as if its not even checking!
public class DBConnector {
Connection connection = null;
String dbURL = "jdbc:mysql://localhost:3306";
String userName;
String password;
public DBConnector() {
// TODO Auto-generated constructor stub
}
public Connection tryConnection(String username, String password){
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(dbURL, username, password);
System.out.println("Connected");
} catch (InstantiationException e) {
System.out.println("No Connection");
e.printStackTrace();
} catch (IllegalAccessException e) {
System.out.println("Connection Refused");
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
System.out.println("Sql Ex");
// TODO Auto-generated catch block
e.printStackTrace();
}
return connection;
}
}
And here is my main class to run the method.
public class MainTest {
public static void main(String[] args) {
DBConnector dbc = new DBConnector();
dbc.tryConnection("", "");
}
}
Maybe this has something to do with running the test on "Localhost"?
Thanks very much!
I would guess that you are logging in as an anonymous user.
You can make your local MySQL Server installation more secure (and hence force your code above to throw an error) by removing the anonymous user like this:
DELETE FROM mysql.user WHERE user='';
FLUSH PRIVILEGES;
Then try connecting with no username and password.