LeakChecker: Practical Static Memory Leak Detection for Managed Languages

40
LeakChecker: Prac,cal Sta,c Memory Leak Detec,on for Managed Languages PRESTO: Program Analyses and So5ware Tools Research Group, Ohio State University Dacong (Tony) Yan 1 , Guoqing Xu 2 , Shengqian Yang 1 , Atanas Rountev 1 1 Ohio State University 2 University of California, Irvine

description

Static detection of memory leaks in a managed language such as Java is attractive because it does not rely on any leak-triggering inputs, allowing compile-time tools to find leaks before software is released. A long-standing issue that prevents practical static memory leak detection for Java is that it can be very expensive to statically determine object liveness in large applications. We present a novel (and the first practical) static leak detection technique that bypasses this problem by considering a common leak pattern. In many cases severe leaks occur in loops where, in each iteration, some objects created by the iteration are unnecessarily referenced by objects external to the loop. These unnecessary references are never used in later loop iterations. Based on this insight, we shift our focus from computing liveness, which is very difficult to achieve precisely and efficiently for large programs, to the easier goal of identifying objects that flow out of a loop but never flow back in. We formalize this analysis using a type and effect system and present its key properties. The analysis was implemented in a tool called LeakChecker and used to detect leaks in eight real-world programs, such as Eclipse, Derby, and log4j. LeakChecker not only identified known leaks, but also discovered new ones whose causes were unknown beforehand, while exhibiting a false positive rate suitable for practical use.

Transcript of LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Page 1: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

LeakChecker:  Prac,cal  Sta,c  Memory  Leak  Detec,on  for  Managed  Languages  

PRESTO:  Program  Analyses  and  So5ware  Tools  Research  Group,  Ohio  State  University  

Dacong  (Tony)  Yan1,  Guoqing  Xu2,  Shengqian  Yang1,  Atanas  Rountev1    

1  Ohio  State  University  2  University  of  California,  Irvine  

   

Page 2: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Memory  Leaks  in  Managed  Languages  •  Languages  such  as  Java  sMll  have  memory  leaks:  unnecessary  references  keep  unused  objects  alive  

•  StaMc  leak  detecMon  – Widely  used  for  unmanaged  languages  such  as  C  – Cannot  be  applied  to  managed  languages:  no  explicit  memory  deallocaMon  

•  General  definiMon  of  leaks  – Precision:  difficult  to  compute  object  liveness  precisely  – Performance:  limited  scalability  for  large  programs  

•  Our  approach  – Shi5  the  focus,  and  idenMfy  common  leak  paVerns  

2  

Page 3: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Proposed  Leak  DetecMon  for  Java  •  ObservaMon:  leaks  are  o5en  related  to  frequently  occurring  events  (e.g.,  loop  iteraMons)  

•  SoluMon:  focus  on  a  user-­‐specified  event  loop  •  ObservaMon:  a  leaking  object  is  o5en  

– created  by  one  loop  iteraMon  – escapes  this  iteraMon  – never  used  in  later  iteraMons  

•  SoluMon:  interprocedural  tracking  of  – whether  an  object  escapes  to  a  memory  locaMon  outside  of  the  loop  

– whether  an  escaping  object  flows  from  the  outside  locaMon  back  into  a  later  loop  iteraMon  3  

Page 4: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

4  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } !

An  example  adapted  from  SPECjbb2000  

Page 5: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

5  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } !

An  example  adapted  from  SPECjbb2000  

Page 6: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

6  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } !

loop  object  

Page 7: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

7  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

outside  object  

loop  object  

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } !

Page 8: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

8  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

outside  object  

loop  object  

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } !

Page 9: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

9  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

outside  object  

loop  object  

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } !

Page 10: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

10  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } !

Page 11: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

11  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } !

Page 12: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

12  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } !

store16  

Page 13: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

13  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } ! Order4 !

store16  

escape  

Transaction1 !

store16  

Page 14: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

14  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } !

store24  

Page 15: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

15  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } ! Order4 !

escape  

Order[]23 ! Customer[]10 !Customer? ! Transaction1 !

store24  

store24     store9  store22     store?    

Page 16: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

16  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } ! Order4,i ! Transaction1 !

store16/prev  

store24/orders,  …,  store9/custs    

Page 17: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

17  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } ! Order4,i ! Transaction1 !

store24/orders,  …,  store9/custs    leaking?  

Page 18: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

18  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } ! Order4,i ! Transaction1 !

store16/prev   leaking?  

Page 19: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

19  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } ! Order4,i ! Transaction1 !

store16/prev   leaking?  

load11  

Page 20: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

20  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } ! Order4,i ! Transaction1 !

store16/prev  

load11  

leaking?  

store16  

Page 21: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

21  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } ! Order4,i ! Transaction1 !

store16/prev  

load11  

leaking?  

store16  

load11/prev  

Page 22: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

22  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } ! Order4,i ! Transaction1 !

store16/prev  

load11  

leaking?  

store16  

load11/prev  (i+1)-­‐th  itera,on  

i-­‐th  itera,on  

Page 23: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Example  

23  

“main”: ! 1 Transaction t = new Transaction(); ! 2 for (int i = 0; i < X; ++i) { ! 3 t.display(); ! 4 Order order = new Order(...); ! 5 t.process(order); ! 6 } !!

7 class Transaction { ! 8 Order prev; ! 9 Customer[] custs = new Customer[…]; !10 void display() { !11 Order r = this.prev; !12 … // display r !13 this.prev = null; // remove !14 } !15 void process(Order p) { !16 this.prev = p; !17 Customer c = this.custs[…]; !18 c.addOrder(p); !19 ... // process p !20 } } !!!

21 class Customer { !22 Order[] orders = new Order[…]; !23 void addOrder(Order q) { !24 this.orders[...] = q; !25 } !26 } ! Order4,i ! Transaction1 !

store16/prev  

store24/orders,  …,  store9/custs    leaking  

non-­‐leaking  

Page 24: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

24  

Page 25: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

25  

Page 26: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

26  

Order4 ! Order[]23 ! Customer[]10 !Customer? ! Transaction1 !store24     store9  store22     store?    

Page 27: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

27  

Page 28: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

28  

Transaction1 !load11/prev  

Order4,i-1 !

Page 29: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

29  

Page 30: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

30  

Transaction1 !outside  object  

Page 31: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

31  

Transaction1 !Order4,i !i-­‐th  itera,on  

outside  object  

Page 32: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

32  

Transaction1 !Order4,i !store16/prev  i-­‐th  itera,on  

outside  object  

Page 33: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

33  

Transaction1 !(i+1)-­‐th  itera,on  

Order4,i !store16/prev  

load11/prev  

i-­‐th  itera,on  

outside  object  

Page 34: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  •  Object:  pair  of  allocaMon  site  and  calling  context  •  Flows-­‐out  path  

– Loop  object  escaping  to  outside  object  – Sequence  of  store  statements  for  the  flow  

•  Flows-­‐in  path  – Escaping  object  flows  from  outside  object  into  the  loop  – Sequence  of  load  statements  causing  the  flow  

•  Loop  iteraMon  constraints  – Flows-­‐in  valid  only  if  the  corresponding  Flows-­‐out  occurs  in  an  earlier  iteraMon  

•  On-­‐demand  analysis  using  context-­‐free  language  reachability  to  match  store/load  and  call/return  

34  

– Captured  by  extended  recency  abstracMon  (ERA)  

Page 35: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

StaMc  Analysis  Outline  (cont.)  •  On-­‐demand  analysis  

– Detect  leaks  only  for  objects  allocated  in  specified  loops  – Context-­‐free  language  reachability  to  match  relevant  store/load  and  call/return  

•  ConservaMve  handling  of  thread  lifeMme  – Assume  the  lifeMme  of  each  thread  exceeds  the  loop  lifeMme  – Capture  objects  leaking  to  long-­‐running  threads  

35  

Page 36: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Analysis  ImplementaMon  •  Memory  leak  

– An  object  leaks  if  it  starts  a  flows-­‐out  path,  but  does  not  have  a  matching  flows-­‐in  path  

•  ReporMng  leaks  – Leaking  object,  with  calling  context  of  its  allocaMon  – Outside  target  object,  with  calling  context  of  its  allocaMon  – Escape-­‐causing  heap  write  (store)  statement,  with  its  calling  context  

•  LeakChecker:  leak  detecMon  tool  built  using  Soot    

36  

Page 37: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

EvaluaMon  •  8  real-­‐world  Java  programs  

– Enterprise  trading,  so5ware  tools,  databases,  logging  – 3  programs  never  studied  by  exisMng  work  

•  EffecMve  for  leak  detecMon?  – LeakChecker  detected  both  known  and  new  leaks  

•  Suitable  for  pracMcal  use?  – Analysis  running  Mme  (all  <  35  mins)  – Reasonable  false  posiMve  rate  (avg  <  50%)  

•  Case  studies  – Performed  to  understand  quality  of  leak  report  – For  each  leak  defect,  pinpoint  root  cause  and  fix  the  problem  in  <  2  hours  37  

Page 38: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Eclipse  Diff  •  Scenario:  compare  two  large  JAR  files  

–  runCompare  method  in  compare  plugin !– An  arMficial  loop  to  invoke  runCompare  mulMple  Mmes  

•  Loop  objects  –  Editor:  display  comparison  results  –  HistoryEntry:  represent  list  of  opened  editors,  and  allow  users  to  navigate  them  backward/forward  

•  Outside  object  –  History:  managed  by  another  plugin  to  save  HistoryEntry  

 

38  

Editor ! History !HistoryEntry!compare  plugin   history  plugin  

!!!!

loop  objects   outside  object  

Page 39: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Conclusions  •  LeakChecker  is  both  effecMve  and  pracMcal  •  Key  insights  

– Capture  common  paVerns  of  leaking  behavior  – Focus  on  user-­‐specified  event  loops  – Report  leaks  with  detailed  context  informaMon  

 

39  

Page 40: LeakChecker: Practical Static Memory Leak Detection for Managed Languages

Thank    you  

40