java - Downloading blob file on JDBC causes memory leak if internet is cutoff during preparedstatement.execute() -
i trying make robust application can download blob files mysql server. files executables or other binary files. download works well, want bullet proof survive internet cutoff midway in download. if internet cutoff occurs before preparedstatement.execute(),everything goes well, memory cleared of garbage , program exits gracefully . on other hand ,if cutoff internet 5 seconds execution of preparedstatement.execute(),the thread downloading hangs indefinitely , never cleared garbage collector , program never exits. main exits,the downloader manager exits,but downloading thread never exits. methodology:
(1)main thread trigger downloadmanager object existence.
(2)downloadermanager object trigggers separate puredownload
object(in separate thread) invoke prepared statement get
binary data make downloads.(3)downloadermanager polls puredownload object detect if cutoff connection has caused become unresponsive , tries kill it.
observing heap dump on netbeans, puredownload object has been cutoff midway in preparestatement never gets garbage collected,and waits indefinitely have tried possible ways :
- (1)thread.isinterrupted() close puredownload object , gced.
- (2)close resultset,statements,connections in separate try catch
never het triggered. - (3)place try catch around preparedstatement.executequery in hope failed internet connection make throw exception , able close remaining objects , exit. no success.
- (4)outputstream.close() , inputsream.close()
- (5)inputstream.read(buffer) placed in thread.interrupted() while loop.
and many other combinations respond closed internet connection midway during download. ahve failed trials. has suggestion?
///////////////////////////////////////main class/////////////////////////////////////////////////
/* * calss launches program , outputs counter on sysout every 1000 milliseocnds.it create downloader manager object in executor. */ package learningthreads; import java.util.concurrent.executorservice; import java.util.concurrent.executors; import java.util.concurrent.future; import java.util.logging.level; import java.util.logging.logger; public class learningthreads { public static void main(string[] args) { executorservice executor = executors.newfixedthreadpool(3); //the object run dwonload on thread downloadermanager dm = new downloadermanager(); future<?> wf = executor.submit(dm); ///just counter on thread give time when events occuring..it ouput numbers on sys out,together other messages other threads. executor.submit(new runnable(){ public void run(){ (int = 0; < 25; i++) { try { system.out.println("the time " + i); thread.sleep(1000); } catch (interruptedexception ex) { logger.getlogger(learningthreads.class.getname()).log(level.severe, null, ex); } } } }); executor.shutdown(); } } //////////////////////////////////end of main class//////////////////////////////////////////////// //////////////////////////////////////////////////downloader manager class///////////////////////////////////////////////////////////////////////////// /* * thhis object manage , monitor puredownload object .its responsibility if keep track of puredownload object doing,and kill if necessary when latter has become unresponsive. *in test, tries kill duredownload object after 15 seconds puredownload object takes around 5-10 seconds connect,and preparedstatement.execute() in full operation after 15 seconds. *so best time cut off internet , see happens. */ package learningthreads; import java.lang.reflect.invocationtargetexception; import java.lang.reflect.method; import java.util.concurrent.callable; import java.util.logging.level; import java.util.logging.logger; /** * * @author dell pc */ public class downloadermanager implements callable{ puredownload pds; thread t; int memoryint=0; int deadbeatcounter=0; private volatile boolean running=true; downloadermanager(){ pds=new puredownload(); t=new thread(pds); t.start(); } @override public object call(){ try { thread.sleep(15000); } catch (interruptedexception ex) { logger.getlogger(downloadermanager.class.getname()).log(level.severe, null, ex); } kill(); return null; } //after various ways of trying kill puredownload object, last resort ,here cam trying kill thread forcefully without practice of terminating thread,as puredwonload object refuses attempt garbage collected. public void kill(){ try { system.out.println("kill"); thread f = t; method m = thread.class.getdeclaredmethod( "stop0" , new class[]{object.class} ); m.setaccessible( true ); m.invoke( f , new threaddeath() ); system.out.println("end kill"); } catch (nosuchmethodexception ex) { logger.getlogger(downloadermanager.class.getname()).log(level.severe, null, ex); } catch (securityexception ex) { logger.getlogger(downloadermanager.class.getname()).log(level.severe, null, ex); } catch (illegalaccessexception ex) { logger.getlogger(downloadermanager.class.getname()).log(level.severe, null, ex); } catch (illegalargumentexception ex) { logger.getlogger(downloadermanager.class.getname()).log(level.severe, null, ex); } catch (invocationtargetexception ex) { logger.getlogger(downloadermanager.class.getname()).log(level.severe, null, ex); } } } /////////////////////////////////////////////////end of downloadermanagerclass///////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////puredownload class//////////////////////////////////////////////////////////////////////// /* *this object actual download. *everything works fine.the problem refuses exit gracefully , garbage collected if internet cutoff occurs 5 seconds after preparedstatement executing. *all standard methods cut off , close obejcts have been tried ,in various combinations . */ package learningthreads; import java.io.file; import java.io.fileoutputstream; import java.io.ioexception; import java.io.inputstream; import java.sql.connection; import java.sql.drivermanager; import java.sql.preparedstatement; import java.sql.resultset; import java.sql.sqlexception; import java.util.concurrent.callable; import java.util.logging.level; import java.util.logging.logger; public class puredownload implements callable,runnable { string dbname = "smsverautodb"; string connectionstring = "jdbc:xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.com:3306/" + dbname; string username = "xxxxxx"; string password = "xxxxxx"; string filename = "file.exe"; string outputpath = "c:\\xxxxxx"; connection conn; inputstream input; private volatile boolean running = true; private volatile int counter=0; downloadermanager dm; resultset rs = null;preparedstatement pstmt; public void stop() { //this function tries kill object memory not responding //various attempts have been made here have stopping method set flags etc. //setting null 1 example system.out.println("puredownload.stop.58"); rs=null; pstmt=null; conn=null; system.out.println(" puredownload.stop.64"); } public void call() throws exception { //this function executes if using executor download(); return null; } @override public void run() { //this function executes if using thread download(); } public void download(){ // update sql string selectsql = "select xxxxx xxxxx x=?"; try { class.forname("com.mysql.jdbc.driver"); conn = drivermanager.getconnection(connectionstring, username, password); pstmt = conn.preparestatement(selectsql); // set parameter; pstmt.setstring(1, filename); system.out.println("physically remove internet connection in 5 seconds when see message"); try { //pstmt.setquerytimeout(2); rs = pstmt.executequery(); } catch (exception e) { system.out.println("trying exception exceute query here,when connection cut off" + e.getmessage()); //pstmt.cancel(); } // write binary stream file string outputpath_2 = outputpath + filename; file file = new file(outputpath_2); fileoutputstream output = new fileoutputstream(file); while (rs.next()) { input = rs.getbinarystream("logiciel"); byte[] buffer = new byte[2048]; while (input.read(buffer) > 0) { output.write(buffer); } } } catch (sqlexception | ioexception e) { logger.getlogger(puredownload.class.getname()).log(level.severe, null, e); } catch (classnotfoundexception ex) { logger.getlogger(puredownload.class.getname()).log(level.severe, null, ex); } { } } } //////////////////////////////////////////////////////////end of puredownload class///////////////////////////////////////////////////////////
asuming use driver mysql provides, can define timeout of socket connections parameter of jdbc url.
http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
sockettimeout
timeout on network socket operations (0, default means no timeout). default: 0
since version: 3.0.1
since default wait indefinitely, try set 10 secs.
Comments
Post a Comment