{"id":854,"date":"2017-09-13T15:21:38","date_gmt":"2017-09-13T14:21:38","guid":{"rendered":"http:\/\/hirt.se\/blog\/?p=854"},"modified":"2017-09-13T17:35:22","modified_gmt":"2017-09-13T16:35:22","slug":"stop-wasting-your-heap","status":"publish","type":"post","link":"https:\/\/hirt.se\/blog\/?p=854","title":{"rendered":"Stop Wasting Your Heap"},"content":{"rendered":"<p>The Java Virtual Machine is a wonderful little piece of software. It provides the illusion of an infinite heap &#8211; as long as you stop referring to instances you no longer need, you can keep going forever. Allocate as many little temporary object as you like; you do not have to worry about running out of memory. The JVM will automatically reclaim the memory when needed. <\/p>\n<p>That said, the amount of memory that you reference at any given time, sometimes referred to as the <strong><em>live set<\/em><\/strong>, is limited by whatever memory is available to the Java heap. If you get an OutOfMemoryError, you either have a memory leak, or your application is trying to keep more memory live than can fit on the heap. <\/p>\n<p>For solving the memory leak case, I will soon be demoing something pretty exciting at JavaOne 2017 that we&#8217;ve been working on (stay tuned). But what if the application is simply keeping alive too much memory? How do you go about reducing the amount of live memory required to run your application?<\/p>\n<p>One way is to limit your application in various ways. Only allow N number of simultaneous users, crank down various caches you may have used in your application to speed up certain operations etc. Another is to try to look at various heap usage patterns that are known to waste heap memory. You usually end up doing a little bit of everything. <\/p>\n<p>There is a little known experimental plug-in for Java Mission Control called JOverflow which can be helpful for estimating how much memory is wasted due to common heap usage anti-patterns.<\/p>\n<h2>Installing JOverflow<\/h2>\n<p>JOverflow can easily be installed from within JMC like this:<\/p>\n<ol>\n<li>Start JMC<\/li>\n<li>Go to <font color=\"#ff0000\">Help | Install New Software<br \/><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13a75ed2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"240\" height=\"173\" title=\"SNAGHTML13a75ed2\" style=\"border: 0px currentcolor\" alt=\"SNAGHTML13a75ed2\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13a75ed2_thumb.png\" border=\"0\"><\/a><\/font><\/li>\n<li>Check <font color=\"#ff0000\">Heap Analysis\/JOverflow<\/font><br \/><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/image.png\"><img loading=\"lazy\" decoding=\"async\" width=\"244\" height=\"190\" title=\"image\" style=\"margin: 0px\" alt=\"image\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/image_thumb.png\" border=\"0\"><\/a><\/li>\n<li>Click <font color=\"#ff0000\">Next<\/font>, <font color=\"#ff0000\">Next<\/font>, and finally accept the license and <font color=\"#ff0000\">Finish<\/font><\/li>\n<\/ol>\n<p>If you are installing into Eclipse, simply use the Experimental update site (can be found from the homepage, <a href=\"http:\/\/oracle.com\/missioncontrol\">http:\/\/oracle.com\/missioncontrol<\/a>)<\/p>\n<h2>The Example<\/h2>\n<p>The example I will be using is a heap dump from an earlier version of Java Mission Control, JMC 4.1.0. In that version we sacrificed quite a lot of heap memory, for a dubious performance optimization.<\/p>\n<blockquote>\n<p>The heap dump can be downloaded from here: <a title=\"jmc41dump.hprof\" href=\"http:\/\/hirt.se\/downloads\/oracle\/joverflow\/jmc41dump.hprof\">jmc41dump.hprof<\/a><\/p>\n<\/blockquote>\n<p>Having the example open in JOverflow will allow you to experiment with the UI, and will likely help facilitate the understanding of the rest of this blog post.<\/p>\n<h2><\/h2>\n<h2><\/h2>\n<h2><\/h2>\n<h2>Understanding the JOverflow User Inteface<\/h2>\n<p>Start by opening a heap dump. If JOverflow is properly installed in JMC (or Eclipse, if running JMC in Eclipse), you should now be presented with the JOverflow user interface.<\/p>\n<p>This is what it looks like on my computer, with the example heap dump (click pictures for full size):<\/p>\n<p><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"644\" height=\"461\" title=\"image\" alt=\"image\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/image_thumb-1.png\" border=\"0\"><\/a><\/p>\n<p>There are four quadrants in the JOverflow user interface. Also notice the little reset button in the upper right corner (<a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/clip_image002.gif\"><img loading=\"lazy\" decoding=\"async\" width=\"20\" height=\"19\" title=\"clip_image002\" style=\"margin: 0px\" alt=\"clip_image002\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/clip_image002_thumb.gif\" border=\"0\"><\/a>). It will reset all the selections in the user interface.<br \/>&nbsp;<\/p>\n<h3><a name=\"_Toc492861525\">Object Selection<\/a><\/h3>\n<p>The top left quadrant,<font color=\"#ff0000\"> Object Selection<\/font>, will show you what heap usage anti-patterns the analysis has found. The first column in the <font color=\"#ff0000\">Object Selection<\/font> table show the kind of objects found, implicitly telling you what was analyzed for. The second how much memory they use in total. The third column, <font color=\"#ff0000\">Overhead<\/font>, shows how much of the memory was wasted, in percent of the total heap used. <\/p>\n<p><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13c3d562.png\"><img loading=\"lazy\" decoding=\"async\" width=\"611\" height=\"589\" title=\"SNAGHTML13c3d562\" style=\"border: 0px currentcolor\" alt=\"SNAGHTML13c3d562\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13c3d562_thumb.png\" border=\"0\"><\/a><\/p>\n<h3><a name=\"_Toc492861526\">Referrer Tree-table<\/a><\/h3>\n<p>The top right quadrant contains the <font color=\"#ff0000\">Referrer<\/font> tree-table. This tree-table will show the aggregated reference chains for whatever is selected. Note that the way to reset the selections in the <font color=\"#ff0000\">Referrer<\/font> tree-table is to <em><strong>right click <\/strong><\/em>in the table. This is since you can make multiple consecutive selections to arrive at the reference chain you are interested in.<\/p>\n<p><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13c68918.png\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"436\" title=\"SNAGHTML13c68918\" style=\"border: 0px currentcolor\" alt=\"SNAGHTML13c68918\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13c68918_thumb.png\" border=\"0\"><\/a><\/p>\n<p>Note that the calculated overhead is all zero. This is since we have not selected the result of any analysis in the Object Selection table yet.<\/p>\n<h3><a name=\"_Toc492861527\">Class Histogram<\/a><\/h3>\n<p>The lower left shows a class histogram for whatever is selected, allowing you to filter on class. <\/p>\n<p><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13cb55ea.png\"><img loading=\"lazy\" decoding=\"async\" width=\"599\" height=\"480\" title=\"SNAGHTML13cb55ea\" style=\"border: 0px currentcolor\" alt=\"SNAGHTML13cb55ea\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13cb55ea_thumb.png\" border=\"0\"><\/a><\/p>\n<p>Note that selections can be done directly in the pie chart. If you want to reset your selection, click the button representing the selection you have made.<\/p>\n<p><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13cd5757.png\"><img loading=\"lazy\" decoding=\"async\" width=\"594\" height=\"480\" title=\"SNAGHTML13cd5757\" style=\"border: 0px currentcolor\" alt=\"SNAGHTML13cd5757\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13cd5757_thumb.png\" border=\"0\"><\/a><\/p>\n<p>Again, note that the Overhead column is still zero. This is since we have not selected the result of any analysis in the <font color=\"#ff0000\">Object Selection<\/font> table. That said, by selecting something directly in the class histogram, without having something selected in the <font color=\"#ff0000\">Object Selection<\/font> table, we can see what analysis is relevant for the selected class.<\/p>\n<h3><a name=\"_Toc492861528\">Ancestor referrer<\/a><\/h3>\n<p>The final table, in the lower right, will show the objects grouped by the closest ancestor referrer. <\/p>\n<p><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13d3cf97.png\"><img loading=\"lazy\" decoding=\"async\" width=\"240\" height=\"186\" title=\"SNAGHTML13d3cf97\" style=\"border: 0px currentcolor\" alt=\"SNAGHTML13d3cf97\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13d3cf97_thumb.png\" border=\"0\"><\/a><\/p>\n<p>It provides a pie chart to show the memory distribution, and filter box, making it easy to home in on instances of classes belonging to specific packages. Now let\u2019s take a look at the actual example.<\/p>\n<h2><\/h2>\n<h2>Reducing Memory Usage \u2013 Example<\/h2>\n<p>From the <font color=\"#ff0000\">Object Selection<\/font> table, it seems we are wasting 17% of our used heap with 710 sparse arrays. Selecting <font color=\"#ff0000\">Sparse Arrays<\/font> in the <font color=\"#ff0000\">Object Selection<\/font> table shows us a lot immediately:<\/p>\n<p><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/image-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1028\" height=\"735\" title=\"image\" alt=\"image\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/image_thumb-2.png\" border=\"0\"><\/a><\/p>\n<p><\/p>\n<p>Almost all of the sparse arrays are Object arrays (see class histogram) accounting for 16% of the heap. The <font color=\"#ff0000\">Referrer<\/font> table-tree and the <font color=\"#ff0000\">Ancestor referrer<\/font> table both show that the field CircularArray.m_array keep holding on 8 of these, and that these 8 instances are responsible for almost all of overhead. So, whilst there are indeed 710 sparse arrays in our system, just 8 are responsible for almost all the heap waste.<\/p>\n<p>We want to know where these circular arrays are being used, so we click the top entry in the <font color=\"#ff0000\">Referrer <\/font>tree-table (remember to use right-click if you want to reset the selections you make here).<\/p>\n<p><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13e08c36.png\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"444\" title=\"SNAGHTML13e08c36\" style=\"border: 0px currentcolor\" alt=\"SNAGHTML13e08c36\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/SNAGHTML13e08c36_thumb.png\" border=\"0\"><\/a><\/p>\n<p>So, it would seem that it is our JMX console attribute subscription storage that is wasting all that memory. This was implemented differently in a later release\u2026<\/p>\n<p>Let\u2019s look at the second offender, the Duplicate Strings. First we reset the user interface (<a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/clip_image002-1.gif\"><img loading=\"lazy\" decoding=\"async\" width=\"20\" height=\"19\" title=\"clip_image002\" style=\"margin: 0px\" alt=\"clip_image002\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/clip_image002_thumb-1.gif\" border=\"0\"><\/a>). Then select Duplicate Strings in the <font color=\"#ff0000\">Object Selection<\/font> table. We immediately recognize that this will be a tougher job, and the law of diminishing returns probably would perhaps make us stop here. That said, it would seem like Eclipse interning some preference related keys, and JMC interning some JMC related Strings would help.<\/p>\n<p>For a more fun example with duplicate strings see the following file: <a title=\"eclipse.hprof\" href=\"http:\/\/hirt.se\/downloads\/oracle\/joverflow\/eclipse.hprof\">eclipse.hprof<\/a>, where various duplicate path segment strings account for a lot of the memory waste:<\/p>\n<p><a href=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/image-3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"644\" height=\"426\" title=\"image\" alt=\"image\" src=\"https:\/\/hirt.se\/blog\/wp-content\/uploads\/2017\/09\/image_thumb-3.png\" border=\"0\"><\/a><\/p>\n<p><em><strong>Note: <\/strong>IIRC I tried this on a more recent version of Eclipse, and it was no longer an issue.<\/em><\/p>\n<h2>Summary<\/h2>\n<ul>\n<li>JOverflow is a plug-in for Java Mission Control<\/li>\n<li>It can be used to identify potentially bad heap usage patterns<\/li>\n<li>Used correctly it can reduce the amount of live memory required to run your application<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>The Java Virtual Machine is a wonderful little piece of software. It provides the illusion of an infinite heap &#8211; as long as you stop referring to instances you no longer need, you can keep going forever. Allocate as many little temporary object as you like; you do not have to worry about running out [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-854","post","type-post","status-publish","format-standard","hentry","category-java-mission-control-fair-dj"],"_links":{"self":[{"href":"https:\/\/hirt.se\/blog\/index.php?rest_route=\/wp\/v2\/posts\/854","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hirt.se\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hirt.se\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hirt.se\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/hirt.se\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=854"}],"version-history":[{"count":9,"href":"https:\/\/hirt.se\/blog\/index.php?rest_route=\/wp\/v2\/posts\/854\/revisions"}],"predecessor-version":[{"id":863,"href":"https:\/\/hirt.se\/blog\/index.php?rest_route=\/wp\/v2\/posts\/854\/revisions\/863"}],"wp:attachment":[{"href":"https:\/\/hirt.se\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=854"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hirt.se\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=854"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hirt.se\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=854"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}