Introducing 

Prezi AI.

Your new presentation assistant.

Refine, enhance, and tailor your content, source relevant images, and edit visuals quicker than ever before.

Loading…
Transcript

Preallocating the heap is one of the reasons that object allocation in Java can be faster than in C/C++. Instead of

allocating memory, the JVM can just move pointers around when

the application wants to create an object. However, preallocating all of this memory leads to comparatively slow

startup times.

The tenured generation is cleaned during a major compaction which is as unpleasant as it sounds. It is slower than a minor compaction and can lead to noticable pauses, but we can deal with those later.

Still not good enough? But wait, there's more.

Clearing out empty generations is cheap.

Copying small numbers of objects is ok.

Divide heap into equal sized sections. Each one behaves like its own generation. G1 concurrently collects in each one and then determines which section will produce the most memory the fastest and only collects those.

Each section can be left alone until its hopefully mostly empty when harvesting the live objects and reclaiming the whole section will be very fast.

Wondering what is taking up all that space? Its time to take a dump.

-XX:+HeapDumpOnOutOfMemoryError

JMX operation com.sun.management:type=HotSpotDiagnostic dumpHeap(String absoluteFilename, boolean collect first)

I've got the heap, now what?

Set variables to null

to help the GC

System.gc()

Pauses

Garbage Collection

Fragmentation

The CMS collector doesn't move live objects so after a while your tenured generation starts to look like swiss cheese.

The thing that allows you to ignore all the details of memory management until it slows your application to a crawl and then you need to understand the details of garbage collection

G1 is supposed to help address this.

Major compactions can lead to unresposive applications for long periods of time, possibly tens of seconds or minutes for incredibly large heaps.

Background threads that run alongside your application, sometimes pausing them, to clean out objects which are no longer referenced from the heap.

The algorithms

http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#available_collectors

G1

-XX:+UseSerialGC - Single threaded copy collector.

Good for small heaps on single processor systems.

How

http://www.fasterj.com/articles/G1.shtml

Good for maximum throughput when pauses are not an issue.

http://drdobbs.com/java/219401061

http://research.sun.com/jtech/pubs/04-g1-paper-ismm.pdf

-XX:+UseParallelGC

Similar to Serial but uses multiple threads and work stealing to utilize multiple processors. Only used on young generation

First available in 1.6.0_14

-XX:+UseParallelOldGC

Same algorithm but used on the tenured generation as well.

Good for minimum pauses

-XX:+UseConcMarkSweepGC

Collects objects while your application threads are running. Stops all threads less than ParallelGC. Usually used with -XX:+ParNewGC to use paralell collector on young generation

Although overall throughput is slightly lower than with ParallelGC CMS reduces pauses by collecting concurrent with your application threads as much as possible. This is only used on the tenured generation and live objects are not moved. This can lead to heap fragmentation over time which requires a major compaction to reorganize. Larger heaps can mitigate this.

Never speak before you measure. How slow is copying objects really?

does Java manage memory?

Why

The Heap

Throughput

do I care?

Desired maximum pause times

-XX:MaxGCPauseMillis

Desired throughput

The heap is usually broken up into generations.

-XX:GCTimeRatio

The eden space is where new objects are allocated.

The vast majority of objects are created and die very quickly. These are harvested during minor compactions.

These compactions move live objects to the survivor spaces

and flatten the Eden space. The speed of this depends on

the ratio of live objects in the space.

Instead of specifying the heap size and generation size and compaction percentages blah blah blah blah

Desired footprint

Just tell the JVM what you want...

Objects that make it to the survivor space and survive enough compactions are moved to the tenured generation. If they have survived this long they are likely to be around for a while.

max and min heap sizes

This space intentionally left blank(unallocated). The heap must be contiguous memory but the JVM only reserves it with the OS until it is needed.

You want as much CPU time as possible for your application.

Ergonomics

The permanent generation stores non-application objects such as class definitions, methods etc.

For really serious detail check out http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#generations

The heap is a large contiguous swath of memory reserved by the

JVM at startup which it manages. All objects created by your

application are allocated in the heap.

It tries for these targets in this order modifying the unspecified ones to reach your specified goals.

Java Memory

Presentation by John Russell (jjrussell@gmail.com)

that aren't expensive for a different reason

Pool objects

Don't

What

You know what helps the GC? Just do your thing.

There's a lot of smart people trying to guess how you code and make the GC work for that. Don't outsmart them.

can I do when its not working?

OutOfMemoryError

What is the GC actually doing?

What kind is it?

http://javabyexample.wisdomplug.com/java-concepts/34-core-java/60-different-types-of-outofmemoryerror-you-can-encounter-in-your-java-application.html

jconsole or visualVM work well for this

You either legitimately need more heap space or your application is leaking. The fun part is finding out which one it is.

-verbose:gc -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

1) Heap memory error

2) Non-heap memory error

3) Native memory error

PermGen space. Just set -XX:MaxPermSize higher (256MB is a huge amount) and move on with your day.

7.777: [GC 7.777: [ParNew: 16000K->2623K(18624K), 0.0331666 secs] 16000K->3270K(81280K), 0.0334059 secs] [Times: user=0.03 sys=0.01, real=0.03 secs]

14.664: [Full GC 14.664: [CMS: 646K->6070K(62656K), 0.1221005 secs] 16144K->6070K(81280K), [CMS Perm : 21247K->21233K(21248K)], 0.1225217 secs] [Times: user=0.11 sys=0.00, real=0.13 secs]

18.546: [GC 18.546: [ParNew: 16000K->2246K(18624K), 0.0137290 secs] 22070K->8317K(81280K), 0.0137942 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

26.226: [GC 26.226: [ParNew: 18246K->2498K(18624K), 0.0112402 secs] 24317K->9977K(81280K), 0.0113014 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

34.314: [GC 34.314: [ParNew: 18498K->1434K(18624K), 0.0059934 secs] 25977K->9765K(81280K), 0.0060549 secs] [Times: user=0.01 sys=0.01, real=0.00 secs]

46.280: [GC 46.280: [ParNew: 17434K->1787K(18624K), 0.0054596 secs] 25765K->10118K(81280K), 0.0055231 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

58.181: [GC 58.182: [ParNew: 17787K->1575K(18624K), 0.0052266 secs] 26118K->9906K(81280K), 0.0052865 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

70.167: [GC 70.167: [ParNew: 17575K->2131K(18624K), 0.0046365 secs] 25906K->10463K(81280K), 0.0046970 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

78.275: [GC 78.275: [ParNew: 18131K->1366K(18624K), 0.0064480 secs] 26463K->9809K(81280K), 0.0065118 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

90.210: [GC 90.210: [ParNew: 17366K->1660K(18624K), 0.0057945 secs] 25809K->10252K(81280K), 0.0058629 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]

jmap comes with the JDK in the bin directory

jmap -histo:live <pid>

Learn by doing at

http://kirk.blog-city.com/why_do_i_have_this_long_gc_pause.htm

Oh you poor, poor person. I'm so sorry.

The OS told you to go away. The problem here is that it may not just be memory. This exception is thrown when the OS tells the JVM that it can't have any number of OS resources for whatever reason. Possible issues are:

  • Unable to create native thread
  • You're out of file handles
  • Your heap is TOO BIG. It can crowd out the native side of the process on 32 bit machines. The whole process can only have 3GB+1GB for the kernel. So if your heap is 2.6GB everything else has to fit in 400MB. Every thread has a native stack allocated, the JVM itself, your birthday wish list, the letter from that girl you knew in highschool... it all has to fit in the native side of the process' memory.

jmap -dump:live,format=b <pid>

num #instances #bytes class name

----------------------------------------------

1: 26062 3259184

2: 26062 3138720

3: 2111 2510488

4: 2111 1838000

5: 39712 1818624

6: 2026 1765792

7: 10319 715296 [C

8: 2327 428168 java.lang.Class

9: 2431 398352 [B

10: 9925 397000 java.lang.String

11: 3409 340552 [[I

12: 3428 272904 [S

13: 2432 222968 [I

14: 4298 206304 java.util.Hashtable$Entry

15: 971 183680 [Ljava.util.HashMap$Entry;

jmap -F -dump:live,format=b <pid>

Please dump the heap and

no seriously, I'm not kidding around, dump the heap before I come over there.

WHY IS THIS NOT THE DEFAULT?!

If your application objects are near the top here you have serious problems

Eclipse MAT

http://www.eclipse.org/mat/

More complex than the federal budget but it comes with awesome sauce.

Learn more about creating dynamic, engaging presentations with Prezi