The document discusses various techniques for improving Java application performance, including:
1. Using tools like JVisualVM and JConsole to analyze performance bottlenecks and determine where to focus optimization efforts.
2. Customizing the Java runtime environment through JVM options and garbage collection settings.
3. Following programming tips like using object scopes and final modifiers efficiently, choosing appropriate collection types, leveraging concurrency constructs properly.
4. Reading further on techniques involving Java I/O, NIO, locks, and lock-free programming.
6. Determine problem Factor to improve? Time or Memory Quantitative analysis to encircle the root causes Use tools to localize memory leak, method call overhead Theoretical argument servers for first-step analysis, but tools provide most convincing information
16. Object Scope String wideScope; for(int i =0; i <10000000; i++) { wideScope = “” + i; } vs for(int i = 0; i < 10000000; i++) { String narrowScope = “” + i; }
17. Heap space is divided into Young Generation and Old Generation spaces JAVA_HOME/jconsole Garbage Collector has best performance on Young Generation Object with narrow scope has more chance to stay in Young Generation
18. Final modifier Protect variable against reference reassignment (non-reflect code) final SafeObject safeObject = new SafeObject(); safeObject = null; // compilation error Modularize code with anonymous class final String displayString = “Hello”; Runnable runnable = new Runnable(){ public void run() { System.out.println(displayString); } };
20. Interaction with Garbage Collector GC (Garbage Collector) reclaims memory occupied by unreferenced object TestObject strongReference = new TestObject(); //variable strongReference //points to memory cells at 0xXXXX strongReference = null; //no reference to cells 0xXXXX System.gc(); //Run the GC GC handles SoftReference , WeakReference and PhantomReference exceptionally JavaDoc from package java.lang.ref
21. //Object is allocated at 0xXXXX TestObject strongReference = new TestObject(); SoftReference<TestObject> softReference = new SoftReference<TestObject>(strongReference); //Object stored at 0xXXX is reachable from softReference strongReference = null; //No more strong reference to object Object stored at 0xXXXX is softly reachable from softReference, but automatically cleaned by GC when there is lack of memory
22. Code from LazyList class of GateIn private static class Batch { private final Reference<Object[]> elements; private Batch(Object[] elements) { this.elements = new SoftReference<Object[]>(elements); } }
23. String String Thread-safe, expensive handling methods StringBuffer Thread-safe, much faster than String StringBuilder Not thread-safe, slightly faster than StringBuffer
24. String s = new String(); for(int i = 0; i < 10000; i++){ s += “a”; } VS StringBuffer buffer = new StringBuffer(); for(int i = 0; i < 10000; i++){ buffer.append(“a”); } VS StringBuilder builder = new StringBuilder(); for(int i = 0; i < 10000; i++){ builder.append(“a”); }
26. Random Access vs Sequential ArrayList<E> access element: O(1) add element at the end: O(1) or O(n) sort element: O(n.logn) (sort with Collections.sort()) LinkedList<E> access element: O(n) add element at both ends: O(1) sort element: O(n.logn) + O(n) (sort with Collections.sort())
27. Initial Allocation Code snippet recurring in eXo products List<String> list = new ArrayList<String>(3); Why hard-coded size? Is it better than List<String> list = new LinkedList<String>();
28. HashMap vs TreeMap HashMap<K,V> fetch <K,V> entry: O(1) put <K,V> entry: O(n) in worst case sort <K,V> entries based on key: Not supported TreeMap<K,V> fetch <K,V> entry: O(1) Put <K,V> entry: O(n) in worst case support sorting entries based on key
29. WeakHashMap private static class Entry<K,V> extends WeakReference<K> implements Map.Entry<K,V> { private V value; private final int hash; private Entry<K,V> next; … . }
30. Java IO and NIO In many cases: gainOf( improve_on_programming_logic ) <<<< gainOf( improve_on_input_output ) Java coder should have knowledge on Java NIO
32. Concurrency concepts Atomicity Code executing on a thread is not inteferenced with other threads Ex: Code incrementing a counter Visibility Change on shared object is visible to multiple threads Ex: Flag variable
33. Atomicity yields Visibility Atomicity problems are more complex than Visibility ones Figure out your concurrency problem ( Atomicity or Visibility ) before typing synchronized
34. Intrinsic lock - synchronized Ensure Atomicity Overhead of synchronized Double-checked pattern 'intrinsic lock extension' in java.util.concurrent.locks
35. private int counter; private void increaseCounter(){ counter++;} private synchronized void increaseCounterUsingIntrinsicLock(){ counter++;} public static void main(String[] args) { int n = 100000; //Print time to call increaseCounter n times //Print time to call increaseCounterUsingIntrinsicLock n times }
37. Double-checked reduces the scope of synchronized block Useful in concurrent initialization problem Requires Visibility on flag_variable
38. Code from RootContainer class in eXo Kernel public static RootContainer getInstance() { RootContainer result = singleton_; if (result == null) { synchronized (RootContainer.class) {….} } }
39. Code from Component class in WebUI Framework public Event getUIComponentEventConfig(String eventName) throws Exception { if(eventMap == null) { synchronized(this) { if(eventMap == null) {…} } } }
40. Volatile keyword Ensure Visibility Work only with atomic operations Usage in double-checked pattern 'volatile extension' in java.util.concurrent.atomic
42. Usage in double-checked pattern Java Memory Model permutes execution order in multi-thread world (JVM Specification) Visibility on flag_variable is mandatory to double-checked pattern volatile boolean flag_variable; //Assumed the type is boolean //Double-checked block