Your SlideShare is downloading. ×
0
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
A topology of memory leaks on the JVM
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

A topology of memory leaks on the JVM

2,088

Published on

A topology of memory leaks on the Java virtual machine. This presentation covers all types of memory leaks that can occur on the JVM and categorizes them after the memory region of their occurrence. …

A topology of memory leaks on the Java virtual machine. This presentation covers all types of memory leaks that can occur on the JVM and categorizes them after the memory region of their occurrence. It further gives some advice on how such leaks can be avoided and presents some debugging techniques.

Published in: Technology, Education
0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,088
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
49
Comments
0
Likes
8
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. A topology of memory leaks on the JVM
  • 2. HotSpot JVM process heap perm gen native stack C sta. user managed string pool method area pc reg. code cache young gen ten. gen const. pool e d e n s r . 1 s r . 2 -Xms -Xmx -Xss -Xsx -XX:PermSize -XX:MaxPermSize (operating system) Java 6 -> 7 Java 7 -> 8
  • 3. genuine leaks HotSpot JVM process heap perm gen native stack C sta. user managed string pool method area pc reg. code cache young gen ten. gen const. pool e d e n s r . 1 s r . 2
  • 4. Field unsafe = Unsafe.class .getDeclaredField("theUnsafe"); unsafe.setAccessible(true); Unsafe theUnsafe = (Unsafe) unsafe.get(null); Allocating native memory with sun.misc.Unsafe 1. Getting hold of “the unsafe“ 2. Allocating native memory final int intSize = 4; long arraySize = (1L + Integer.MAX_VALUE) * intSize; long index = unsafe.allocateMemory(arraySize); Random random = new Random(); for(long l = 0L; l < arraySize; l++) unsafe.putInt(random.nextInt()); 3. (Hopefully) releasing native memory // Without me, the memory leaks unsafe.freeMemory(index);
  • 5. I don‘t do sun.misc.Unsafe 1. But some of your favorite tools do: 1. Kryo (used by e.g. Twitter‘s Storm, Apache Hive) 2. EhCache‘s “big memory“ (used by e.g. Hibernate) 3. JDK (e.g. direct byte buffers) 4. General purpose (e.g. GSON, Snappy) 2. Unsafe to become public API in Java 9 (competition with CLR?) 3. JNI leaks have the same effect 4. Java 8 removes “perm gen“ in favor of native memory “meta space“
  • 6. symptoms of a genuine leak No exception required by JVMS. However, JVM will be untypical slow when: 1. Creating a thread: Requires allocation of new stacks / pc register. 2. Loading a class / JIT: Requires native memory. 3. Doing I/O: Often requires native memory. 4. Calling a native method: Allocates resources on native stack / user space. Swapping can delay execution. 5. Garbage collection: Tenured generation collection needs broad access such that OS must swap back the heap. Rule of thump: All JVM heaps must be swapped back into memory. (Leaked memory will stay swapped out.)
  • 7. Heap leaks HotSpot JVM process heap perm gen native stack C sta. user managed string pool method area pc reg. code cache young gen ten. gen const. pool e d e n s r . 1 s r . 2
  • 8. class FixedSizeStack { private final Object[] objectPool = new Object[10]; private int pointer = -1; public Object pop() { if(pointer < 0) throw new NoSuchElementException(); return objectPool[pointer--]; } public Object peek() { if(pointer < 0) throw new NoSuchElementException(); return objectPool[pointer]; } public void push(Object object) { if(pointer > 8) throw new IllegalStateException("stack overflow"); objectPool[++pointer] = object; } }
  • 9. Element 5 Element 4 Element 3 Element 2 Element 1 Element 0 Stack All memory leaks in Java are linked to reference life cycles.
  • 10. Immutable Stack Element 0 Immutable Stack Element 1 Immutable Stack Element 2
  • 11. public String substring(int beginIndex, int endIndex) { // omitted argument validation return ((beginIndex == 0) && (endIndex == count)) ? this : new String(offset + beginIndex, endIndex - beginIndex, value); } String(int offset, int count, char[] value) { this.value = value; this.offset = offset; this.count = count; } JDK 6
  • 12. XML, anybody? org.xml.sax.DocumentHandler { // several callback methods void characters(char[] ch, int start, int length); } Webpage character blob DocumentHandler few letter word is defined by produces handles
  • 13. public String substring(int beginIndex, int endIndex) { // omitted argument validation int subLen = endIndex - beginIndex; return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); } public String(char[] value, int offset, int count) { // omitted argument validation this.value = Arrays.copyOfRange(value, offset, offset + count); } JDK 7
  • 14. interface Message extends Serializable { String getInfo(); } class ExampleActivity extends Activity { @Override public void onCreate(Bundle bundle) { startService( new Intent(this, getClass()) .putExtra( "foo", new Message() { @Override public String getInfo() { return "bar"; } })); } } A classic Android leak
  • 15. class ExampleActivity$1 implements Message { private ExampleActivity this$0; ExampleActivity$1(ExampleActivity this$0) { this.this$0 = this$0; } @Override public String getInfo() { return "bar"; } } new Message() { @Override public String getInfo() { return "bar"; } } uncompiled desugared Non-static inner classes
  • 16. class Foo { void bar() { List<String> list = Arrays.asList("foo", "bar"); list.forEach(LambdaMetafactory .INVOKEDYNAMIC(Foo::lambda$1) .make()); } private static void lambda$1(String s) { System.out.println(s); } } class Foo { void bar() { List<String> list = Arrays.asList("foo", "bar"); list.forEach(s -> { System.out.println(s); }); } } uncompiled desugared Java 8 lambda expressions
  • 17. class Foo { final String prefix; // constructor omitted void bar() { List<String> list = Arrays.asList("foo", "bar"); list.forEach(s -> { System.out.println( prefix + ":" + s) }); } } uncompiled desugared Java 8 lambda expressions class Foo { final String prefix; // constructor omitted void bar() { List<String> list = Arrays.asList("foo", "bar"); list.forEach(LambdaMetaFactory .INVOKEDYNAMIC(this::lambda$1) .make()); } private void lambda$1(String s) { System.out.println(this.prefix + ":" + s); } }
  • 18. uncompiled desugared class Foo { final String prefix; // constructor omitted void bar() { List<String> list = Arrays.asList("foo", "bar"); String prefix = this.prefix; list.forEach(s -> { System.out.println( prefix + ":" + s)}); } } class Foo { final String prefix; // constructor omitted void bar() { List<String> list = Arrays.asList("foo", "bar"); String prefix = this.prefix; list.forEach(LambdaMetafactory .INVOKEDYNAMIC(Foo::lambda$1) .make(prefix)); } private static void lambda$1(String prefix, String s) { System.out.println(prefix + ":" + s); } } Java 8 lambda expressions
  • 19. Other typical causes of heap leaks • Functional expressions in e.g. Scala / Groovy • Serialization leaks (e.g. Apache Wicket) • Singletons / enums • Context frameworks (e.g. DI like Spring)
  • 20. Stack leaks HotSpot JVM process heap perm gen native stack C sta. user managed string pool method area pc reg. code cache young gen ten. gen const. pool e d e n s r . 1 s r . 2
  • 21. class StackLeak { int SIZE = (int) (0.5 * Runtime .getRuntime() .maxMemory()); void foo() { { byte[] array1 = new byte[SIZE]; } byte[] array2 = new byte[SIZE]; } void bar() { { byte[] array1 = new byte[SIZE]; } byte[] array2 = new byte[10]; byte[] array3 = new byte[SIZE]; } }
  • 22. this void foo() { { byte[] array1 = new byte[SIZE]; } byte[] array2 = new byte[SIZE]; } array1 SIZEarray1SIZEarray2 localvariablearray operandstack
  • 23. this void bar() { { byte[] array1 = new byte[SIZE]; } byte[] array2 = new byte[1]; byte[] array3 = new byte[SIZE]; } array1array2 SIZEarray11array2SIZEarray3 array3 localvariablearray operandstack
  • 24. “Perm gen“ leaks HotSpot JVM process heap perm gen native stack C sta. user managed string pool method area pc reg. code cache young gen ten. gen const. pool e d e n s r . 1 s r . 2
  • 25. new Foo() Foo.class getClass() ClassLoader() getClassLoader() Field field = ClassLoader.class.getDeclaredField("classes"); field.setAccessible(true); Vector<Class<?>> classes = (Vector<Class<?>>) field.get(ClassLoader.getSystemClassLoader()); classes Bar.class Classes and HotSpot Foo.klass MA Bar.klass
  • 26. ClassLoaders and HotSpot null ClassLoader() ClassLoader() ClassLoader() ClassLoader() bootstrap CL (bootstrap directory) extension CL (extension directory) system CL (class path) user CL (explicit) parent parent parent parent Foo.class loadClass()
  • 27. ClassLoader() Thread.class Foo()Foo.class Thread() FooHolder.class threadLocalMap class loader leak ClassLoader() class FooHolder { static ThreadLocal<Foo> tlFoo = new ThreadLocal<Foo>(); static { tlFoo.set(new Foo()); } }
  • 28. Other typical causes of class loader leaks • Shut down hooks • Use of thread context class loaders (e.g. OSGi) • Service provider interfaces (SPIs) • JDBC drivers (JDK DriverManager) • Security frameworks (e.g. JDK Policy) • Class loader magic (e.g. instrumentation)
  • 29. Why do modern applications require so much perm gen memory? class Foo { public Object bar(Object o) { return o; } } Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Foo.class); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return proxy.invokeSuper(obj, doSomethindWith(args)); }}); Foo enhancedFoo = (Foo) enhancer.create(); Created classes: 2 + #methods * 2 [FastClass, FastMethod, MethodProxy]
  • 30. Modern JDK‘s inflation works similarly Method MethodAccessor DelegatingMethod- AccessorImpl NativeMethod- AccessorImpl invoked by after inflation (byte code generation) before inflation (JNI)
  • 31. Java 8 meta space • Permanent generation rebranded (and probably approximation to JRockit) • Meta space is allocated in native memory • No space limit by default (MaxMetaspaceSize) • Today‘s debugging tools will not be able to read meta space
  • 32. Tenuring leaks HotSpot JVM process heap perm gen native stack C sta. user managed string pool method area pc reg. code cache young gen ten. gen const. pool e d e n s r . 1 s r . 2
  • 33. public void foo() { Set<Bar> bars = new HashSet<Bar>(); for(int i = 0; i < 100; i++) { for(int j = 0; j < 100; j++) { bars.add(makeBar(i, j)); } doSomethingWith(bars); bars.clear(); } } public void foo() { for(int i = 0; i < 100; i++) { Set<Bar> bars = new HashSet<Bar>(); for(int j = 0; j < 100; j++) { bars.add(makeBar(i, j)); } doSomethingWith(bars); } } young generation Tenured generation eden survivor 1 survivor 2 bars bars bars bars collection of survivor 2collection of survivor 1
  • 34. Implicit memory leaks • Leaked threads: Require fixed amount of memory for call stacks / pc register / general allocation • Leaked handles (files, sockets, databases): Usually require JVM memory resources
  • 35. debugging / profiling jmap -dump:live,format=b,file=<...> <pid> java -XX:+HeapDumpOnOutOfMemoryError -XX:+HeapDumpPath=<...> <...> jhat <hprof file> select a from [I a where a.length >= 256 GUI tools: MAT (Eclipse RCP) / JVisualVM / HeapWalker
  • 36. http://rafael.codes @rafaelcodes http://documents4j.com https://github.com/documents4j/documents4j http://bytebuddy.net https://github.com/raphw/byte-buddy

×