410 likes | 691 Views
Java Memory Management. Charles-François THUEUX Sitraka Inc. cft@sitraka.com. Overview. Review of Java’s Memory Model Loitering Objects Effective Memory Management Design Implementation Documentation Conclusion and Further Reading. Memory Safety in Java.
E N D
Java Memory Management Charles-François THUEUX Sitraka Inc. cft@sitraka.com
Overview • Review of Java’s Memory Model • Loitering Objects • Effective Memory Management • Design • Implementation • Documentation • Conclusion and Further Reading Stuttgart JUG 2001
Memory Safety in Java • A key aspect in the design of... • the Java Language • no pointer arithmetic • the Java Virtual Machine (JVM) • bytecode instruction set • runtime checks (array bounds, ref casts) • garbage collection Stuttgart JUG 2001
Memory Safety in Java • Eliminated many memory-related problems • Buffer overruns • De-referencing stale pointers • Memory leaks • However Java programs can exhibit the macro-level symptoms of traditional memory leaks • Process size seemingly grows without bounds Stuttgart JUG 2001
Java’s Memory Model • The intent of Garbage Collection is to remove objects that are no longer needed • Undecidable in general • Java uses an approximation • remove objects that are no longer reachable • The reachability test starts at the Heap’s root set Stuttgart JUG 2001
The Root Set • Set of foundational object references • static reference fields within class definitions • local reference variables within the method frames of each Java thread stack • The contents of the Root Set change dynamically as your program runs • As threads enter and exit methods, local reference variables enter and leave the Root Set Stuttgart JUG 2001
The Dynamic Root Set - 1 1 public 2 class MyApp 3 { 4 private static MyAppmyApp = null; 5 6 public static 7 void 8 main( String[] args ) 9 { 10 myApp = new MyApp( ); 11 myApp.method1( ); 12 myApp.method2( ); 13 } Consider a single thread of execution... Root Set: MyApp myApp String[] args Stuttgart JUG 2001
The Dynamic Root Set - 2 14 private void 15 method1( ) 16 { 17 BigObjectbigObj = new BigObject( ); 18 ... 19 } 20 21 private void 22 method2( ) 23 { 24 BiggerObjectbiggerObj = new BiggerObject( ); 25 ... 26 } 27 } Root Set: MyApp myApp String[] args BigObject bigObj Stuttgart JUG 2001
The Dynamic Root Set - 3 1 public 2 class MyApp 3 { 4 private static MyAppmyApp = null; 5 6 public static 7 void 8 main( String[] args ) 9 { 10 myApp = new MyApp( ); 11 myApp.method1( ); 12 myApp.method2( ); 13 } Root Set: MyApp myApp String[] args Stuttgart JUG 2001
The Dynamic Root Set - 4 14 private void 15 method1( ) 16 { 17 BigObjectbigObj = new BigObject( ); 18 ... 19 } 20 21 private void 22 method2( ) 23 { 24 BiggerObjectbiggerObj = new BiggerObject( ); 25 ... 26 } 27 } Root Set: MyApp myApp String[] args BiggerObject biggerObj Stuttgart JUG 2001
The Dynamic Root Set - 5 1 public 2 class MyApp 3 { 4 private static MyAppmyApp = null; 5 6 public static 7 void 8 main( String[] args ) 9 { 10 myApp = new MyApp( ); 11 myApp.method1( ); 12 myApp.method2( ); 13 } Root Set: MyApp myApp Stuttgart JUG 2001
Reachable Objects • Elements within the Root Set refer to objects within the JVM’s Heap • Reference variables within those objects refer to further objects within the Heap Root Set Object Reference Stuttgart JUG 2001
Object States • Define three progressive object “states” • Allocated • Exists within the JVM’s heap • Reachable • A path exists (directly or indirectly) from a member of the root set, through a sequence of references, to that object. • Live • From the intent of the application’s design, the program will use the object (meaning at least one of its fields will be accessed and/or one of its methods will be invoked) along some future path of execution. Stuttgart JUG 2001
Memory leak in C/C++ (handled by JVM’s GC) “Memory leak” in Java The JVM Heap allocated reachable live Stuttgart JUG 2001
C/C++ vs. Java • Memory leak in C/C++ • Object was allocated, but it’s not reachable • malloc()/new, but forgot to free()/delete before destroying the memory pointer • “Memory leak” in Java • The object is reachable, but it’s not live • a reference was set, but it hasn’t been eliminated • Object is reachable to the GC, but the source code to fix the leak may not be available to you Stuttgart JUG 2001
“Memory Leaks” in Java • Impact is often more severe than C/C++ • Rarely a single object, but a wholesub-graph • A single lingering reference can have massive memory impact (and a significant performance impact) Unintentional reference Stuttgart JUG 2001
Loitering Objects • The term “Memory Leak” has too much historical baggage from C/C++ • and it doesn’t accurately describe the formulation of the problem as it pertains to Java • A new term: Loitering Object • An object that remains within the Heap past its useful life Stuttgart JUG 2001
Reference Management • The key to effective memory management in Java is effective reference management • What undermines effective reference management ? • Awareness of the issue • Bad habits from C/C++ development • Class Libraries and Application Frameworks • Ill-defined reference management policies • Encapsulate flawed reference assignments Stuttgart JUG 2001
Reference Management • As a Java programmer, how can I effectively manage references within my software, and promote better reference management ? 1. Design 2. Implementation 3. Documentation Stuttgart JUG 2001
1. Design for Ref. Mgmt. • For each Use Case within your application, explicitly characterize: a. The lifecycle of each object b. The inter-relationships between various objects Stuttgart JUG 2001
Lifecycle Relationships • Object B adopts A’s lifecycle and has no control over it A B Stuttgart JUG 2001
1a. Object Lifecycles • For each object within the Use Case you are implementing, you need to explicitly define: • its point of creation • the duration of its usefulness • the point at which it should be eliminated from the runtime environment Stuttgart JUG 2001
1a. Object Lifecycles • In Java, creating an object within the runtime environment is an explicit act, while its elimination is an implicit one • Defining - within your design - the point when your object should be eliminated will help you validate the correctness of your Java implementation Stuttgart JUG 2001
1b. Inter-Object Relationships • Objects establish relationships as they collaborate to accomplish their goals • Examples: • Composition (a has-a relationship) • Association (a uses-a relationship) • Relationship lifecycles Stuttgart JUG 2001
1b. Inter-Object Relationships • Think “Symmetry” • If you define a method that establishes a relationship, ensure you define a method that revokes it. • The Observer Pattern subject.addObserver( Observer ) subject.removeObserver( Observer ) Stuttgart JUG 2001
2. Implementation • Loitering objects often arise from simple coding oversights or omissions • forgot to null-ify a variable • didn’t remove an object from a list • Use a Heap Analysis Tool to validate that your implementation adheres to your design Stuttgart JUG 2001
Reference Variable Scope • Three forms of reference variables: • Class-based: • Reference variables within a class definition that have a static attribute associated with them • Object-based: • Non static reference variables within a class definition • Method-based: • Reference variables defined within the scope of a method Stuttgart JUG 2001
Reference Variable Scope • Don’t be concerned about assignments to method-based reference variables within methods of short execution time • Be attentive of assignments to class-based and object-based reference variables, and method-based reference variables within methods of long execution times Stuttgart JUG 2001
Lingerer • Reference used transiently by long-term object • Reference always reset on next use • e.g. associations with menu items • e.g. global action or service Stuttgart JUG 2001
Lingerer Example • Print action as singleton • class Printer… • has data member Printable target; • calls target.doPrint(); • target inside printer not set to null on completion • target is a lingering reference • target cannot be GC’ed until next print Stuttgart JUG 2001
Lingerer Strategies • Don’t use a set of fields to maintain state • enclose in object • easier to maintain • one reference to clean up • Draw state diagram • quiescent state == no outgoing references • Early exit methods or multi-stage process • setup; process; cleanup Stuttgart JUG 2001
3. Documentation • For methods that establish a relationship to another object, identify (in your javadoc description) the symmetric method that revokes the relationship void addObserver( Observer ) Adds the Observer argument to the subject's internal set of observers. To remove the observer from this internal set, invoke the removeObserver( Observer ) method. Stuttgart JUG 2001
Dealing with Flaws of Others • After determining you have a loitering object, your investigation reveals that the object holding the reference to your loiterer is one which you do not have the source code to. • How do you handle this ? Stuttgart JUG 2001
Using Their Code Properly ? • Are you using their framework properly ? • Understand their notion of object life cycles • Think symmetry (again) • An add() operation implies a remove() • A register() implies an unregister() • Does the symmetric operation (to the one that established the reference) remove it ? Stuttgart JUG 2001
Notify the Author • You’ve established that they are erroneously holding an object reference • Create a simple test case • Make it easy for the vendor to clearly identify the issue. • Ask for • Work arounds (if possible) • Resolution to the fundamental problem Stuttgart JUG 2001
Eliminate Subgraph Elements • If you can not fix the root cause, free up as much of the loitering subgraph as you can. Unintentional reference Unintentional reference Stuttgart JUG 2001
Conclusion • The key to effective memory management in Java is effective reference management • Incorporate reference management in your design • Validate your Java implementation • Document your reference management policies so others will know what to do Stuttgart JUG 2001
Further Reading • Loitering Objects and Java Framework Design by Leonard Slipp, JavaReport, Volume 6, Number 1 (January 2001) http://www.javareport.com/html/from_pages/article.asp?id=249&mon=1&yr=2001 • How Do You Plug Java Memory Leaks ? by Ethan Henry and Ed Lycklama, Dr. Dobb’s Journal, Java Q&A Column,Volume 25, Number 2 (February 2000) www.ddj.com/articles/2000/0002/0002l/0002l.htm • Memory Leaks in Java Programs by Joel Nylund, JavaReport, Volume 4, Number 11 (November 1999). www.javareport.com/archive/9911/html/from_pages/ftp_feature.shtml Stuttgart JUG 2001