Effective interprocedural resource leak detection Emina Torlak and Satish Chandra IBM T.J. Watson Research Center Hawthorne, NY
Resource leaks in Java void test(File file, String enc) throws IOException { PrintWriter out = null; Unlike memory, system resources must be try { manually managed try { out = new PrintWriter( ‣ FileOutputStream, Socket, Connection, … new OutputStreamWriter( new FileOutputStream(file), enc)); } catch (UnsupportedEncodingException ue) { out = new PrintWriter(new FileWriter(file)); } out.append(‘c’); } catch (IOException e) { } finally { if (out != null) out.close(); } } Simplified code excerpt from ANT 2
Resource leaks in Java void test(File file, String enc) throws IOException { PrintWriter out = null; Unlike memory, system resources must be try { manually managed try { out = new PrintWriter( ‣ FileOutputStream, Socket, Connection, … new OutputStreamWriter( new FileOutputStream(file), enc)); } catch (UnsupportedEncodingException ue) { out = new PrintWriter(new FileWriter(file)); } out.append(‘c’); } catch (IOException e) { close() releases } finally { the resource if (out != null) out.close(); } } Simplified code excerpt from ANT 2
Resource leaks in Java void test(File file, String enc) throws IOException { PrintWriter out = null; Unlike memory, system resources must be try { manually managed try { out = new PrintWriter( ‣ FileOutputStream, Socket, Connection, … new OutputStreamWriter( new FileOutputStream(file), enc)); } catch (UnsupportedEncodingException ue) { Manual resource management is tricky out = new PrintWriter(new FileWriter(file)); } ‣ a resource must be released on all paths out.append(‘c’); } catch (IOException e) { } finally { if (out != null) out.close(); } } Simplified code excerpt from ANT 3
Resource leaks in Java void test(File file, String enc) throws IOException { PrintWriter out = null; Unlike memory, system resources must be try { manually managed try { out = new PrintWriter( ‣ FileOutputStream, Socket, Connection, … new OutputStreamWriter( new FileOutputStream(file), enc)); } catch (UnsupportedEncodingException ue) { Manual resource management is tricky out = new PrintWriter(new FileWriter(file)); } ‣ a resource must be released on all paths out.append(‘c’); } catch (IOException e) { handle to the } finally { FileOutputStream is if (out != null) lost, so it’s never out.close(); closed } } Simplified code excerpt from ANT 3
Resource leaks in Java Unlike memory, system resources must be manually managed ‣ FileOutputStream, Socket, Connection, … Manual resource management is tricky ‣ a resource must be released on all paths Leaks lead to performance problems ‣ crashes, gradual performance degradation Excerpt from an online bug database 4
Resource leaks in Java Unlike memory, system resources must be manually managed ‣ FileOutputStream, Socket, Connection, … Manual resource management is tricky ‣ a resource must be released on all paths Leaks lead to performance problems ‣ crashes, gradual performance degradation Excerpt from an online bug database 4
T RACKER : engineering a leak detector for the real world core resource analysis algorithm heuristics for better usability ‣ inteprocedural tracking of must- ‣ ranking of leak reports access paths ‣ filtering of reports due to unlikely ‣ avoids whole-program alias exceptions analysis precision ‣ clustering of reports for nested resources scalability actionability 5
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { fis = new FileInputStream(f); Report a leak when all access isr = new InputStreamReader(fis, e); } finally { paths to an unreleased if (isr != null) resource go out of scope … isr.close(); } } Tracking FileInputStream 6
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { fis = new FileInputStream(f); Report a leak when all access isr = new InputStreamReader(fis, e); } finally { paths to an unreleased if (isr != null) resource go out of scope … isr.close(); } } normal flow Tracking FileInputStream 7
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { • [•, { fis }] fis = new FileInputStream(f); Report a leak when all access isr = new InputStreamReader(fis, e); } finally { paths to an unreleased if (isr != null) resource go out of scope … isr.close(); } } normal flow Tracking FileInputStream 7
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { • [•, { fis }] fis = new FileInputStream(f); Report a leak when all access [•, { fis, isr.sd.in }] isr = new InputStreamReader(fis, e); } finally { paths to an unreleased if (isr != null) resource go out of scope … isr.close(); } } normal flow Tracking FileInputStream 7
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { • [•, { fis }] fis = new FileInputStream(f); Report a leak when all access [•, { fis, isr.sd.in }] isr = new InputStreamReader(fis, e); } finally { paths to an unreleased [•, { fis, isr.sd.in }] if (isr != null) resource go out of scope … isr.close(); } } normal flow Tracking FileInputStream 7
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { • [•, { fis }] fis = new FileInputStream(f); Report a leak when all access [•, { fis, isr.sd.in }] isr = new InputStreamReader(fis, e); } finally { paths to an unreleased [•, { fis, isr.sd.in }] if (isr != null) resource go out of scope … ✓ isr.close(); } } normal flow resource released: stop tracking it Tracking FileInputStream 7
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { fis = new FileInputStream(f); Report a leak when all access isr = new InputStreamReader(fis, e); } finally { paths to an unreleased if (isr != null) resource go out of scope … isr.close(); } } exceptional flow Tracking FileInputStream 8
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { • [•, { fis }] fis = new FileInputStream(f); Report a leak when all access isr = new InputStreamReader(fis, e); } finally { paths to an unreleased if (isr != null) resource go out of scope … isr.close(); } } exceptional flow Tracking FileInputStream 8
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { • [•, { fis }] fis = new FileInputStream(f); Report a leak when all access [•, { fis }] isr = new InputStreamReader(fis, e); } finally { paths to an unreleased if (isr != null) resource go out of scope … isr.close(); } } exceptional flow Tracking FileInputStream 8
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { • [•, { fis }] fis = new FileInputStream(f); Report a leak when all access [•, { fis }] isr = new InputStreamReader(fis, e); } finally { paths to an unreleased [•, { fis }] if (isr != null) resource go out of scope … isr.close(); } } exceptional flow Tracking FileInputStream 8
Core resource tracking algorithm Use a local, precise aliasing void test(File f, String e) throws IOException { abstraction to track access InputStreamReader isr = null; paths to unreleased resources FileInputStream fis = null; try { • [•, { fis }] fis = new FileInputStream(f); Report a leak when all access [•, { fis }] isr = new InputStreamReader(fis, e); } finally { paths to an unreleased [•, { fis }] if (isr != null) resource go out of scope … [•, { fis }] isr.close(); } } exceptional flow Tracking FileInputStream 8
Recommend
More recommend