Effective interprocedural resource leak detection Emina Torlak and - - PowerPoint PPT Presentation

effective interprocedural resource leak detection
SMART_READER_LITE
LIVE PREVIEW

Effective interprocedural resource leak detection Emina Torlak and - - PowerPoint PPT Presentation

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


slide-1
SLIDE 1

Emina Torlak and Satish Chandra

IBM T.J. Watson Research Center Hawthorne, NY

Effective interprocedural resource leak detection

slide-2
SLIDE 2

Unlike memory, system resources must be manually managed

  • FileOutputStream, Socket, Connection, …

void test(File file, String enc) throws IOException { PrintWriter out = null; try { try {

  • ut = new PrintWriter(

new OutputStreamWriter( new FileOutputStream(file), enc)); } catch (UnsupportedEncodingException ue) {

  • ut = new PrintWriter(new FileWriter(file));

}

  • ut.append(‘c’);

} catch (IOException e) { } finally { if (out != null)

  • ut.close();

} }

Resource leaks in Java

2

Simplified code excerpt from ANT

slide-3
SLIDE 3

Unlike memory, system resources must be manually managed

  • FileOutputStream, Socket, Connection, …

void test(File file, String enc) throws IOException { PrintWriter out = null; try { try {

  • ut = new PrintWriter(

new OutputStreamWriter( new FileOutputStream(file), enc)); } catch (UnsupportedEncodingException ue) {

  • ut = new PrintWriter(new FileWriter(file));

}

  • ut.append(‘c’);

} catch (IOException e) { } finally { if (out != null)

  • ut.close();

} }

Resource leaks in Java

2

Simplified code excerpt from ANT close() releases the resource

slide-4
SLIDE 4

void test(File file, String enc) throws IOException { PrintWriter out = null; try { try {

  • ut = new PrintWriter(

new OutputStreamWriter( new FileOutputStream(file), enc)); } catch (UnsupportedEncodingException ue) {

  • ut = new PrintWriter(new FileWriter(file));

}

  • ut.append(‘c’);

} catch (IOException e) { } finally { if (out != null)

  • ut.close();

} }

Unlike memory, system resources must be manually managed

  • FileOutputStream, Socket, Connection, …

Manual resource management is tricky

  • a resource must be released on all paths

Resource leaks in Java

3

Simplified code excerpt from ANT

slide-5
SLIDE 5

void test(File file, String enc) throws IOException { PrintWriter out = null; try { try {

  • ut = new PrintWriter(

new OutputStreamWriter( new FileOutputStream(file), enc)); } catch (UnsupportedEncodingException ue) {

  • ut = new PrintWriter(new FileWriter(file));

}

  • ut.append(‘c’);

} catch (IOException e) { } finally { if (out != null)

  • ut.close();

} }

Unlike memory, system resources must be manually managed

  • FileOutputStream, Socket, Connection, …

Manual resource management is tricky

  • a resource must be released on all paths

Resource leaks in Java

3

handle to the FileOutputStream is lost, so it’s never closed Simplified code excerpt from ANT

slide-6
SLIDE 6

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

Resource leaks in Java

4

Excerpt from an online bug database

slide-7
SLIDE 7

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

Resource leaks in Java

4

Excerpt from an online bug database

slide-8
SLIDE 8

TRACKER: engineering a leak detector for the real world

5

scalability precision actionability core resource analysis algorithm

  • inteprocedural tracking of must-

access paths

  • avoids whole-program alias

analysis

heuristics for better usability

  • ranking of leak reports
  • filtering of reports due to unlikely

exceptions

  • clustering of reports for nested

resources

slide-9
SLIDE 9

Core resource tracking algorithm

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

6 void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Tracking FileInputStream

slide-10
SLIDE 10

Core resource tracking algorithm

7

normal flow

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

Tracking FileInputStream

slide-11
SLIDE 11

Core resource tracking algorithm

7

normal flow

[•, { fis }]

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

Tracking FileInputStream

slide-12
SLIDE 12

Core resource tracking algorithm

7

normal flow

[•, { fis }] [•, { fis, isr.sd.in }]

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

Tracking FileInputStream

slide-13
SLIDE 13

Core resource tracking algorithm

7

normal flow

[•, { fis }] [•, { fis, isr.sd.in }] [•, { fis, isr.sd.in }]

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

Tracking FileInputStream

slide-14
SLIDE 14

Core resource tracking algorithm

7

normal flow

[•, { fis }] [•, { fis, isr.sd.in }] [•, { fis, isr.sd.in }]

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

Tracking FileInputStream

  • resource released:

stop tracking it

slide-15
SLIDE 15

Core resource tracking algorithm

8

exceptional flow Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Tracking FileInputStream

slide-16
SLIDE 16

Core resource tracking algorithm

8

exceptional flow

[•, { fis }]

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Tracking FileInputStream

slide-17
SLIDE 17

Core resource tracking algorithm

8

exceptional flow

[•, { fis }] [•, { fis }]

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Tracking FileInputStream

slide-18
SLIDE 18

Core resource tracking algorithm

8

exceptional flow

[•, { fis }] [•, { fis }] [•, { fis }]

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Tracking FileInputStream

slide-19
SLIDE 19

Core resource tracking algorithm

8

exceptional flow

[•, { fis }] [•, { fis }] [•, { fis }] [•, { fis }]

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Tracking FileInputStream

slide-20
SLIDE 20

Core resource tracking algorithm

8

exceptional flow

[•, { fis }] [•, { fis }] [•, { fis }] [•, { }] resource leaking: no handles left [•, { fis }]

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Tracking FileInputStream

slide-21
SLIDE 21

Core resource tracking algorithm

8

exceptional flow

[•, { fis }] [•, { fis }] [•, { fis }] [•, { }] resource leaking: no handles left [•, { fis }]

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope …

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

Tracking FileInputStream

  • w

i t n e s s e d l e a k

slide-22
SLIDE 22

Core resource tracking algorithm

9

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope … or if the number or length of access paths is too large

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

Tracking at most 3 paths of length 1 to FileInputStream (d = 1, b = 3)

normal flow

slide-23
SLIDE 23

Core resource tracking algorithm

9

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope … or if the number or length of access paths is too large

[•, { fis }]

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

Tracking at most 3 paths of length 1 to FileInputStream (d = 1, b = 3)

normal flow

slide-24
SLIDE 24

Core resource tracking algorithm

9

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope … or if the number or length of access paths is too large

[•, { fis }] [•, { }]

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

Tracking at most 3 paths of length 1 to FileInputStream (d = 1, b = 3)

normal flow

resource assumed to leak: cannot track {fis, isr.sd.in}

slide-25
SLIDE 25

Core resource tracking algorithm

9

Use a local, precise aliasing abstraction to track access paths to unreleased resources Report a leak when all access paths to an unreleased resource go out of scope … or if the number or length of access paths is too large

[•, { fis }] [•, { }]

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

Tracking at most 3 paths of length 1 to FileInputStream (d = 1, b = 3)

a s s u m e d l e a k normal flow

resource assumed to leak: cannot track {fis, isr.sd.in}

slide-26
SLIDE 26

Soundness: all true positives reported regardless of the limits on d and b Monotonicity: false positives decrease monotonically as d or b increase Witnessed reports are much more likely to be true positives than assumed reports

Key properties of the core tracking algorithm

10

false positive true positive

slide-27
SLIDE 27

Soundness: all true positives reported regardless of the limits on d and b Monotonicity: false positives decrease monotonically as d or b increase Witnessed reports are much more likely to be true positives than assumed reports

Key properties of the core tracking algorithm

10

false positive true positive d = 1, b = 3

slide-28
SLIDE 28

Soundness: all true positives reported regardless of the limits on d and b Monotonicity: false positives decrease monotonically as d or b increase Witnessed reports are much more likely to be true positives than assumed reports

Key properties of the core tracking algorithm

10

false positive true positive d = 1, b = 3 d = 3, b = 5

slide-29
SLIDE 29

Soundness: all true positives reported regardless of the limits on d and b Monotonicity: false positives decrease monotonically as d or b increase Witnessed reports are much more likely to be true positives than assumed reports

Key properties of the core tracking algorithm

10

false positive true positive d = 1, b = 3 d = 3, b = 5 d = 5, b = 5

slide-30
SLIDE 30

Soundness: all true positives reported regardless of the limits on d and b Monotonicity: false positives decrease monotonically as d or b increase Witnessed reports are much more likely to be true positives than assumed reports

Key properties of the core tracking algorithm

10

false positive true positive d = 1, b = 3 d = 3, b = 5 d = 5, b = 5 W A

slide-31
SLIDE 31

Heuristics for better usability: leak report prioritization

11

Tracking FileInputStream with d = 1, b = 3

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (isr != null) isr.close(); } }

[•, { fis }] [•, { fis }] [•, { fis }] [•, { }] [•, { fis }]

witnessed leak h i g h p r i

  • r

i t y

  • [•, { fis }]

[•, { }]

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

Tracking FileInputStream with d = 1, b = 3

l

  • w

p r i

  • r

i t y assumed leak

slide-32
SLIDE 32

Heuristics for better usability: ignoring unlikely exceptions

12 void test(File f, String e) throws IOException { FileInputStream fis = null; try { fis = new FileInputStream(f); } catch (IOException e) { } Integer i = new Integer(0); if (fis != null) fis.close(); }

?

slide-33
SLIDE 33

Heuristics for better usability: ignoring unlikely exceptions

12 void test(File f, String e) throws IOException { FileInputStream fis = null; try { fis = new FileInputStream(f); } catch (IOException e) { } Integer i = new Integer(0); if (fis != null) fis.close(); }

may throw an OutOfMemoryError, but unlikely

?

slide-34
SLIDE 34

Heuristics for better usability: ignoring unlikely exceptions

12 void test(File f, String e) throws IOException { FileInputStream fis = null; try { fis = new FileInputStream(f); } catch (IOException e) { } Integer i = new Integer(0); if (fis != null) fis.close(); }

may throw an OutOfMemoryError, but unlikely

?

slide-35
SLIDE 35

Heuristics for better usability: ignoring unlikely exceptions

Many exceptions are unlikely to occur in practice, leading to spurious leak reports

  • OutOfMemoryError, ClassFormatError, …

Report only leaks due to exceptions that are anticipated by the programmer

  • declared, thrown or caught

13 void test(File f, String e) throws IOException { FileInputStream fis = null; try { fis = new FileInputStream(f); } catch (IOException e) { } Integer i = new Integer(0); if (fis != null) fis.close(); }

n

  • l

e a k

may throw an OutOfMemoryError, but unlikely

slide-36
SLIDE 36

Heuristics for better usability: nested resources

14 void test(File f, String e) throws IOException { InputStreamReader isr = new InputStreamReader( new FileInputStream(f), e); } void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

Tracking FileInputStream and InputStreamReader

slide-37
SLIDE 37

Heuristics for better usability: nested resources

14 void test(File f, String e) throws IOException { InputStreamReader isr = new InputStreamReader( new FileInputStream(f), e); } void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

Tracking FileInputStream and InputStreamReader

?

slide-38
SLIDE 38

Heuristics for better usability: nested resources

14 void test(File f, String e) throws IOException { InputStreamReader isr = new InputStreamReader( new FileInputStream(f), e); } void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

wrapper not closed but the wrapped resource is Tracking FileInputStream and InputStreamReader

?

slide-39
SLIDE 39

Heuristics for better usability: nested resources

14 void test(File f, String e) throws IOException { InputStreamReader isr = new InputStreamReader( new FileInputStream(f), e); } void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

wrapper not closed but the wrapped resource is Tracking FileInputStream and InputStreamReader

? ?

slide-40
SLIDE 40

Heuristics for better usability: nested resources

14 void test(File f, String e) throws IOException { InputStreamReader isr = new InputStreamReader( new FileInputStream(f), e); } void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

wrapper not closed but the wrapped resource is wrapper and wrapped resource are both leaking Tracking FileInputStream and InputStreamReader

? ?

slide-41
SLIDE 41

Heuristics for better usability: nested resources

15 void test(File f, String e) throws IOException { InputStreamReader isr = new InputStreamReader( new FileInputStream(f), e); }

a l e a k c l u s t e r

void test(File f, String e) throws IOException { InputStreamReader isr = null; FileInputStream fis = null; try { fis = new FileInputStream(f); isr = new InputStreamReader(fis, e); } finally { if (fis != null) fis.close(); } }

n

  • l

e a k

wrapper not closed but the wrapped resource is wrapper and wrapped resource are both leaking

Report a wrapper leak only if it wraps a leaking system resource Present the wrapper and resource leak as a single problem (i.e., a leak cluster)

slide-42
SLIDE 42

Evaluating TRACKER

16 150,000 300,000 450,000 600,000 A

N T

1 . 7 B

A T I K

1 . 6 B

I R T

2 . 5 F

R O S T W I R E

4 . 1 7 T

O M C A T

6 .

102,220 127,363 572,744 97,048 63,033 9,981 16,279 69,293 11,187 6,952

Application size # classes # methods

Five large open-source benchmarks

  • ANT 1.7, BATIK 1.6, BIRT 2.5, FROSTWIRE

4.17, TOMCAT 6.0

Effectiveness: true vs. false positive rate

  • of witnessed and assumed reports
  • with or without exception filtering
  • with or without wrapper clustering

Performance

  • effects on fact richness on performance

Comparison to FINDBUGS

slide-43
SLIDE 43

Evaluating TRACKER

16 150,000 300,000 450,000 600,000 A

N T

1 . 7 B

A T I K

1 . 6 B

I R T

2 . 5 F

R O S T W I R E

4 . 1 7 T

O M C A T

6 .

102,220 127,363 572,744 97,048 63,033 9,981 16,279 69,293 11,187 6,952

Application size # classes # methods

Five large open-source benchmarks

  • ANT 1.7, BATIK 1.6, BIRT 2.5, FROSTWIRE

4.17, TOMCAT 6.0

Effectiveness: true vs. false positive rate

  • of witnessed and assumed reports
  • with or without exception filtering
  • with or without wrapper clustering

Performance

  • effects on fact richness on performance

Comparison to FINDBUGS

slide-44
SLIDE 44

Evaluating TRACKER: effectiveness

Highly ranked reports more likely to be true positives than low ranked reports Most high rank true positives found with small limits on path length & number Minimal true positive rate: 84%

17 30 60 90 120 150 〈 1 , 3 〉 〈 3 , 3 〉 〈 3 , 5 〉 〈 5 , 5 〉 〈 1 , 1 〉 Ant 1.7 # of reports 〈path length, # of paths〉 high rank true positives low rank true positives high rank false positives low rank false positives

slide-45
SLIDE 45

Evaluating TRACKER: performance

18

Only minutes to analyze applications with millions of lines of code Slower with larger limits on the length and number of tracked paths

15 30 45 60 〈 1 , 3 〉 〈 3 , 3 〉 〈 3 , 5 〉 〈 5 , 5 〉 〈 1 , 1 〉 Analysis time vs fact size analysis time (sec) 〈path length, # of paths〉

BATIK ANT FROSTWIRE TOMCAT BIRT

slide-46
SLIDE 46

Final thoughts

Tracker provides precise, scalable resource leak detection

  • millions of lines of code analyzed in minutes
  • average true positive rate of more than 80% percent
  • ships in the Rational Software Analyzer 7.1

Future work

  • leverage application-specific usage patterns for higher

quality reports

  • build on prior work (ISMM 2008) to add automatic

resource disposal

19