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!
Related
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)
could you please have a look at my code :
private void initSocket() {
try {
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.bind(null);
socketChannel.connect(new InetSocketAddress(host,port));
while(! socketChannel.finishConnect() ){
Thread.sleep(5);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void initOutput() {
outBuffer = ByteBuffer.allocateDirect(512); //Allocate direct for better performance (no java-heap alloc)
outBuffer.clear();
}
private void initInput() {
inBuffer = ByteBuffer.allocateDirect(1024); //Allocate direct for better performance (no java-heap alloc)
inBuffer.clear();
}
public String in () {
try {
while (socketChannel.re)
socketChannel.read(inBuffer);
inBuffer.mark();
final String ret = Charset.forName("UTF-8").newDecoder().decode(inBuffer).toString();
bulletin.PIPE_IN.Info.push(" <<< ", new String[]{"TsPipe2","in"}, new Object[]{ret, inBuffer});
return ret;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void out (String out) {
outBuffer.clear();
outBuffer.put(out.getBytes());
//Write all in one go
bulletin.PIPE_OUT.Info.push(" >>> ", new String[]{"TsPipe2","out"}, new Object[]{outBuffer, out});
int toWrite = outBuffer.remaining();
for (int i = 0; i < toWrite; ++i) {
try {
i += socketChannel.write(outBuffer);
Thread.sleep(Period.NIO_CHANNEL_WRITE_SLEEP.getValue());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
And tell me what am I doing wrong ?
As the topic states I am always getting the same data from the in-method and am not sure wether my out-method works or not
I travelled throught several tutorials now and it might be I mixed something up.
I also found promising stuff on stackoverflow - but nothing ever worked.
As a little background info - I am writing a Teamspeak bot communicatin via Sockets with a TS-Server and have gone pretty far. From the moment I first heard about nio I wanted to migrate to it.
Are their other frameworks to consider ? heard Google Grizzly is pretty neat, but not sure if it's useful for my case ?
I believe you're missing some braces at this while (socketChannel.re) loop.
I have a Java program in which I am doing some JDBC for select queries. Will it be advisable to call testDataBase() each time which inturns calls DBConnection() each time or I should reuse one connection for all the queries. Thanks in advance.
private void testDataBase(String query){
Connection con = DBConnection();
Statement st = null;
ResultSet rs = null;
try {
st = con.createStatement();
rs = st.executeQuery(query);
boolean flag = true;
while (rs.next()) {
String resultString = "";
for(int i = 1; i <=rs.getMetaData().getColumnCount();i++){
resultString=resultString+" "+ rs.getString(i);
}
System.out.println(resultString);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
private Connection DBConnection() {
final String method_name = "DBConnection";
Connection conn = null;
try{
Class.forName(driver).newInstance();
conn = java.sql.DriverManager.getConnection(url,userName,password);
}catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
} catch (SQLException e) {
System.out.println(e.getMessage());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return conn;
}
Opening a DB connection is an expensive operation in terms of perfofmance. You should use a ConnectionPool for sharing connections among different requests.
Connections are not thread safe, so sharing them across requests is not a good idea.
A better idea is to pool connections and keep their scope as narrow as possible: check the connection out of the pool, use it, close it in transaction scope.
Database connections are long-running and should be re-used, unless you have a very low query rate.
Getting a database connection is quite an expensive operation, so it is advisable to re-use a connection if possible. Consider also using connection pooling, which will maintain a number of connections for you, so you can just grab one from the pool when needed. The method shown above might not need to change, it depends on the DBConnection() method you call.
I completely agree with #Amir Kost, in terms of performances, opening a DB connection in one of the slowest operation that you can do, and if you have restrictive real time constraints it could be a big issue.
I do not know if you are using a framework or not, but a good practice is to publish a bean which wrap a pool of connection and every time that you need to interact directly with the db, you get the current open connection (which usually corresponds to a so called "session").
I suggest to you, (even if you are not using any framework) to reproduce this technicality.
If you want only one instance of Connection, you can make use of the Singleton pattern, you can consider :
public class Connector {
private static final String URL = "jdbc:mysql://localhost/";
private static final String LOGIN = "root";
private static final String PASSWORD = "azerty";
private static final String DBNAME = "videotheque";
private static Connector connector;
private static Connection connection;
private Connector() {
}
public synchronized static Connector getInstance() {
if (connector == null) {
connector = new Connector();
}
return connector;
}
public static Connection getConnection() {
if (connection == null) {
Connection c = null;
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
c = DriverManager.getConnection(URL + DBNAME, LOGIN, PASSWORD);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return c;
}
return connection;
}
}
And then, you can call : Connector.getInstance().getConnection()
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.