Merge "[277422] Use fast indexed lookup for primitive class types"
diff --git a/features/org.eclipse.mat.chart.feature/feature.properties b/features/org.eclipse.mat.chart.feature/feature.properties
index e312a8e..c431ce2 100644
--- a/features/org.eclipse.mat.chart.feature/feature.properties
+++ b/features/org.eclipse.mat.chart.feature/feature.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2009, 2018 SAP AG, IBM Corporation and others.
+# Copyright (c) 2009, 2019 SAP AG, IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -29,7 +29,7 @@
 
 # "copyright" property - text of the "Feature Update Copyright"
 copyright=\
-Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others.\n\
+Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.\n\
 All rights reserved. This program and the accompanying materials\n\
 are made available under the terms of the Eclipse Public License v1.0\n\
 which accompanies this distribution, and is available at\n\
diff --git a/features/org.eclipse.mat.chart.feature/feature.xml b/features/org.eclipse.mat.chart.feature/feature.xml
index e7b70d7..ac70faa 100644
--- a/features/org.eclipse.mat.chart.feature/feature.xml
+++ b/features/org.eclipse.mat.chart.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature

       id="org.eclipse.mat.chart.feature"

       label="%featureName"

-      version="1.8.1.qualifier"

+      version="1.9.1.qualifier"

       provider-name="%providerName"

       plugin="org.eclipse.mat.chart">

 

@@ -30,8 +30,8 @@
       <import plugin="org.eclipse.birt.chart.device.swt" version="2.3.0" match="greaterOrEqual"/>

       <import plugin="org.eclipse.birt.chart.engine.extension" version="2.3.0" match="greaterOrEqual"/>

       <import plugin="org.eclipse.birt.core" version="2.3.0" match="greaterOrEqual"/>

-      <import plugin="org.eclipse.mat.ui" version="1.8.1" match="greaterOrEqual"/>

-      <import feature="org.eclipse.mat.feature" version="1.8.1" match="greaterOrEqual"/>

+      <import plugin="org.eclipse.mat.ui" version="1.9.1" match="greaterOrEqual"/>

+      <import feature="org.eclipse.mat.feature" version="1.9.1" match="greaterOrEqual"/>

    </requires>

 

    <plugin

diff --git a/features/org.eclipse.mat.chart.feature/pom.xml b/features/org.eclipse.mat.chart.feature/pom.xml
index 7b13fa7..7e1e50c 100644
--- a/features/org.eclipse.mat.chart.feature/pom.xml
+++ b/features/org.eclipse.mat.chart.feature/pom.xml
@@ -9,7 +9,7 @@
     <groupId>org.eclipse.mat</groupId>

     <artifactId>parent</artifactId>

     <relativePath>../../parent</relativePath>

-    <version>1.8.1-SNAPSHOT</version>

+    <version>1.9.1-SNAPSHOT</version>

   </parent>

 

   <artifactId>org.eclipse.mat.chart.feature</artifactId>

diff --git a/features/org.eclipse.mat.feature/about.mappings b/features/org.eclipse.mat.feature/about.mappings
index 5b4a719..971fdee 100644
--- a/features/org.eclipse.mat.feature/about.mappings
+++ b/features/org.eclipse.mat.feature/about.mappings
@@ -9,4 +9,4 @@
 #*    IBM Corporation - initial API and implementation and/or initial documentation

 #*******************************************************************************

 #Build

-0=1.8.1

+0=1.9.1

diff --git a/features/org.eclipse.mat.feature/feature.properties b/features/org.eclipse.mat.feature/feature.properties
index 9aa4c4b..bf060d4 100644
--- a/features/org.eclipse.mat.feature/feature.properties
+++ b/features/org.eclipse.mat.feature/feature.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others.
+# Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -32,7 +32,7 @@
 
 # "copyright" property - text of the "Feature Update Copyright"
 copyright=\
-Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others.\n\
+Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.\n\
 All rights reserved. This program and the accompanying materials\n\
 are made available under the terms of the Eclipse Public License v1.0\n\
 which accompanies this distribution, and is available at\n\
diff --git a/features/org.eclipse.mat.feature/feature.xml b/features/org.eclipse.mat.feature/feature.xml
index ec76a54..bb91834 100644
--- a/features/org.eclipse.mat.feature/feature.xml
+++ b/features/org.eclipse.mat.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature

       id="org.eclipse.mat.feature"

       label="%featureName"

-      version="1.8.1.qualifier"

+      version="1.9.1.qualifier"

       provider-name="%providerName"

       plugin="org.eclipse.mat.api">

    <install-handler/>

diff --git a/features/org.eclipse.mat.feature/pom.xml b/features/org.eclipse.mat.feature/pom.xml
index 6142911..75d71d4 100644
--- a/features/org.eclipse.mat.feature/pom.xml
+++ b/features/org.eclipse.mat.feature/pom.xml
@@ -9,7 +9,7 @@
     <groupId>org.eclipse.mat</groupId>

     <artifactId>parent</artifactId>

     <relativePath>../../parent</relativePath>

-    <version>1.8.1-SNAPSHOT</version>

+    <version>1.9.1-SNAPSHOT</version>

   </parent>

 

   <artifactId>org.eclipse.mat.feature</artifactId>

diff --git a/features/org.eclipse.mat.ui.rcp.feature/feature.properties b/features/org.eclipse.mat.ui.rcp.feature/feature.properties
index d62a22d..c71e75c 100644
--- a/features/org.eclipse.mat.ui.rcp.feature/feature.properties
+++ b/features/org.eclipse.mat.ui.rcp.feature/feature.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others.
+# Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -29,7 +29,7 @@
 
 # "copyright" property - text of the "Feature Update Copyright"
 copyright=\
-Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others.\n\
+Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.\n\
 All rights reserved. This program and the accompanying materials\n\
 are made available under the terms of the Eclipse Public License v1.0\n\
 which accompanies this distribution, and is available at\n\
diff --git a/features/org.eclipse.mat.ui.rcp.feature/feature.xml b/features/org.eclipse.mat.ui.rcp.feature/feature.xml
index b1bd1f3..6e11dde 100644
--- a/features/org.eclipse.mat.ui.rcp.feature/feature.xml
+++ b/features/org.eclipse.mat.ui.rcp.feature/feature.xml
@@ -2,7 +2,7 @@
 <feature

       id="org.eclipse.mat.ui.rcp.feature"

       label="%featureName"

-      version="1.8.1.qualifier"

+      version="1.9.1.qualifier"

       provider-name="%providerName"

       plugin="org.eclipse.mat.ui.rcp">

 

diff --git a/features/org.eclipse.mat.ui.rcp.feature/pom.xml b/features/org.eclipse.mat.ui.rcp.feature/pom.xml
index d9bfefa..b141baf 100644
--- a/features/org.eclipse.mat.ui.rcp.feature/pom.xml
+++ b/features/org.eclipse.mat.ui.rcp.feature/pom.xml
@@ -9,7 +9,7 @@
     <groupId>org.eclipse.mat</groupId>

     <artifactId>parent</artifactId>

     <relativePath>../../parent</relativePath>

-    <version>1.8.1-SNAPSHOT</version>

+    <version>1.9.1-SNAPSHOT</version>

   </parent>

 

   <artifactId>org.eclipse.mat.ui.rcp.feature</artifactId>

diff --git a/org.eclipse.mat.product/mat.product b/org.eclipse.mat.product/mat.product
index d11341c..63666c4 100644
--- a/org.eclipse.mat.product/mat.product
+++ b/org.eclipse.mat.product/mat.product
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>

 <?pde version="3.5"?>

 

-<product name="Memory Analyzer Tool" uid="org.eclipse.mat.ui.rcp.MemoryAnalyzer" id="org.eclipse.mat.ui.rcp.MemoryAnalyzer" application="org.eclipse.mat.ui.rcp.application" version="1.8.1" useFeatures="true" includeLaunchers="true">

+<product name="Memory Analyzer Tool" uid="org.eclipse.mat.ui.rcp.MemoryAnalyzer" id="org.eclipse.mat.ui.rcp.MemoryAnalyzer" application="org.eclipse.mat.ui.rcp.application" version="1.9.1" useFeatures="true" includeLaunchers="true">

 

    <aboutInfo>

       <image path="/org.eclipse.mat.ui.rcp/icons/eclipse_lg.gif"/>

       <text>

          Eclipse Memory Analyzer
 
-Version: 1.8.1
+Version: 1.9.1
 
-Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others. All rights reserved.
+Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others. All rights reserved.
 Visit http://www.eclipse.org/mat

       </text>

    </aboutInfo>

@@ -172,7 +172,7 @@
    </license>

 

    <copyright>

-Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others.

+Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.

 All rights reserved. This program and the accompanying materials

 are made available under the terms of the Eclipse Public License v1.0

 which accompanies this distribution, and is available at

diff --git a/org.eclipse.mat.product/pom.xml b/org.eclipse.mat.product/pom.xml
index 89c9330..ab4c6ea 100644
--- a/org.eclipse.mat.product/pom.xml
+++ b/org.eclipse.mat.product/pom.xml
Binary files differ
diff --git a/org.eclipse.mat.targetdef/pom.xml b/org.eclipse.mat.targetdef/pom.xml
index b2519b0..09631a6 100644
--- a/org.eclipse.mat.targetdef/pom.xml
+++ b/org.eclipse.mat.targetdef/pom.xml
@@ -13,7 +13,7 @@
 		<groupId>org.eclipse.mat</groupId>

 		<artifactId>parent</artifactId>

 		<relativePath>../parent</relativePath>

-		<version>1.8.1-SNAPSHOT</version>

+		<version>1.9.1-SNAPSHOT</version>

 	</parent>

 

   <artifactId>org.eclipse.mat.targetdef</artifactId>

diff --git a/org.eclipse.mat.updatesite/pom.xml b/org.eclipse.mat.updatesite/pom.xml
index 7134e17..6278c3d 100644
--- a/org.eclipse.mat.updatesite/pom.xml
+++ b/org.eclipse.mat.updatesite/pom.xml
@@ -7,7 +7,7 @@
 		<groupId>org.eclipse.mat</groupId>

 		<artifactId>parent</artifactId>

 		<relativePath>../parent</relativePath>

-		<version>1.8.1-SNAPSHOT</version>

+		<version>1.9.1-SNAPSHOT</version>

 	</parent>

 

 	<artifactId>org.eclipse.mat.updatesite</artifactId>

diff --git a/parent/pom.xml b/parent/pom.xml
index c3edd9c..62c3567 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -10,7 +10,7 @@
 

 	<groupId>org.eclipse.mat</groupId>

 	<artifactId>parent</artifactId>

-	<version>1.8.1-SNAPSHOT</version>

+	<version>1.9.1-SNAPSHOT</version>

 	<packaging>pom</packaging>

 

 	<name>MAT Parent</name>

diff --git a/plugins/org.eclipse.mat.api/.settings/.api_filters b/plugins/org.eclipse.mat.api/.settings/.api_filters
index 85e67d3..6bea27f 100644
--- a/plugins/org.eclipse.mat.api/.settings/.api_filters
+++ b/plugins/org.eclipse.mat.api/.settings/.api_filters
@@ -15,24 +15,4 @@
             </message_arguments>

         </filter>

     </resource>

-    <resource path="src/org/eclipse/mat/snapshot/SnapshotFactory.java" type="org.eclipse.mat.snapshot.SnapshotFactory">

-        <filter id="1143996420">

-            <message_arguments>

-                <message_argument value="openSnapshot(File, Map&lt;String,String&gt;, IProgressListener)"/>

-            </message_arguments>

-        </filter>

-    </resource>

-    <resource path="src/org/eclipse/mat/snapshot/SnapshotFactory.java" type="org.eclipse.mat.snapshot.SnapshotFactory$Implementation">

-        <filter id="405901410">

-            <message_arguments>

-                <message_argument value="org.eclipse.mat.snapshot.SnapshotFactory.Implementation"/>

-                <message_argument value="openSnapshot(File, IProgressListener)"/>

-            </message_arguments>

-        </filter>

-        <filter id="1211105284">

-            <message_arguments>

-                <message_argument value="openSnapshot(File, Map&lt;String,String&gt;, IProgressListener)"/>

-            </message_arguments>

-        </filter>

-    </resource>

 </component>
\ No newline at end of file
diff --git a/plugins/org.eclipse.mat.api/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.api/META-INF/MANIFEST.MF
index 190480e..d085f17 100644
--- a/plugins/org.eclipse.mat.api/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.api/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name

 Bundle-Vendor: %Bundle-Vendor

 Bundle-SymbolicName: org.eclipse.mat.api;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Export-Package: org.eclipse.mat.inspections.osgi;x-friends:="org.eclipse.mat.ui",

  org.eclipse.mat.inspections.osgi.model;x-friends:="org.eclipse.mat.ui",

  org.eclipse.mat.internal.acquire;x-friends:="org.eclipse.mat.ui",

diff --git a/plugins/org.eclipse.mat.api/about.mappings b/plugins/org.eclipse.mat.api/about.mappings
index 5b4a719..971fdee 100644
--- a/plugins/org.eclipse.mat.api/about.mappings
+++ b/plugins/org.eclipse.mat.api/about.mappings
@@ -9,4 +9,4 @@
 #*    IBM Corporation - initial API and implementation and/or initial documentation

 #*******************************************************************************

 #Build

-0=1.8.1

+0=1.9.1

diff --git a/plugins/org.eclipse.mat.api/about.properties b/plugins/org.eclipse.mat.api/about.properties
index 0d43e10..f97cc3e 100644
--- a/plugins/org.eclipse.mat.api/about.properties
+++ b/plugins/org.eclipse.mat.api/about.properties
@@ -1,5 +1,5 @@
 #*******************************************************************************
-#* Copyright (c) 2010, 2018 IBM Corporation.
+#* Copyright (c) 2010, 2019 IBM Corporation.
 #* All rights reserved. This program and the accompanying materials
 #* are made available under the terms of the Eclipse Public License v1.0
 #* which accompanies this distribution, and is available at
@@ -13,7 +13,7 @@
 Version: {featureVersion}\n\
 Build id: {0}\n\
 \n\
-Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others.\n\
+Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.\n\
 All rights reserved. This program and the accompanying materials\n\
 are made available under the terms of the Eclipse Public License v1.0\n\
 which accompanies this distribution, and is available at\n\
diff --git a/plugins/org.eclipse.mat.api/plugin.xml b/plugins/org.eclipse.mat.api/plugin.xml
index da8578e..6ecf1d7 100644
--- a/plugins/org.eclipse.mat.api/plugin.xml
+++ b/plugins/org.eclipse.mat.api/plugin.xml
Binary files differ
diff --git a/plugins/org.eclipse.mat.api/pom.xml b/plugins/org.eclipse.mat.api/pom.xml
index 0bb3cc2..d6c0206 100644
--- a/plugins/org.eclipse.mat.api/pom.xml
+++ b/plugins/org.eclipse.mat.api/pom.xml
Binary files differ
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/CommonNameResolver.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/CommonNameResolver.java
index 7c6bc04..8855977 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/CommonNameResolver.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/CommonNameResolver.java
@@ -102,7 +102,7 @@
         public String resolve(IObject heapObject) throws SnapshotException

         {

             Object value = heapObject.resolveValue("value"); //$NON-NLS-1$

-            return value != null ? String.valueOf(value) : null; 

+            return value != null ? String.valueOf(value) : null;

         }

     }

 

@@ -431,37 +431,47 @@
     {

         public String resolve(IObject obj) throws SnapshotException

         {

-            IObject cls = (IObject)obj.resolveValue("declaringClass");

-            IObject methodName = (IObject)obj.resolveValue("methodName");

+            IObject cls = (IObject)obj.resolveValue("declaringClass"); //$NON-NLS-1$

+            IObject methodName = (IObject)obj.resolveValue("methodName"); //$NON-NLS-1$

             if (cls == null || methodName == null)

                 return null;

-            int line = (Integer)obj.resolveValue("lineNumber");

-            IObject fn = (IObject)obj.resolveValue("fileName");

+            int line = (Integer)obj.resolveValue("lineNumber"); //$NON-NLS-1$

+            IObject fn = (IObject)obj.resolveValue("fileName"); //$NON-NLS-1$

             String ln;

             if (line == -2)

-                ln = "(Compiled Code)";

+                ln = "(Compiled Code)"; //$NON-NLS-1$

             else if (line == -3)

-                ln = "(Native Method)";

+                ln = "(Native Method)"; //$NON-NLS-1$

             else if (line == -1)

-                ln = "";

+                ln = ""; //$NON-NLS-1$

             else if (line == 0)

-                ln = "";

+                ln = ""; //$NON-NLS-1$

             else

                 ln = Integer.toString(line);

             String name;

             if (fn == null)

                 if (line > 0)

-                    name = cls.getClassSpecificName() + "." + methodName.getClassSpecificName() + "() " + ln;

+                    name = cls.getClassSpecificName() + "." + methodName.getClassSpecificName() + "() " + ln; //$NON-NLS-1$ //$NON-NLS-2$

                 else

-                    name = cls.getClassSpecificName() + "." + methodName.getClassSpecificName() + "()";

+                    name = cls.getClassSpecificName() + "." + methodName.getClassSpecificName() + "()";  //$NON-NLS-1$//$NON-NLS-2$

             else

                 if (line > 0)

-                    name = cls.getClassSpecificName() + "." + methodName.getClassSpecificName() + "() ("

-                                + fn.getClassSpecificName() + ":" + ln + ")";

+                    name = cls.getClassSpecificName() + "." + methodName.getClassSpecificName() + "() (" //$NON-NLS-1$ //$NON-NLS-2$

+                                + fn.getClassSpecificName() + ":" + ln + ")";  //$NON-NLS-1$//$NON-NLS-2$

                 else

-                    name = cls.getClassSpecificName() + "." + methodName.getClassSpecificName() + "() ("

-                                    + fn.getClassSpecificName() + ")";

+                    name = cls.getClassSpecificName() + "." + methodName.getClassSpecificName() + "() (" //$NON-NLS-1$ //$NON-NLS-2$

+                                    + fn.getClassSpecificName() + ")"; //$NON-NLS-1$

             return name;

         }

     }

+

+    @Subject("java.lang.Enum")

+    public static class EnumResolver implements IClassSpecificNameResolver

+    {

+        public String resolve(IObject heapObject) throws SnapshotException

+        {

+            IObject value = (IObject) heapObject.resolveValue("name"); //$NON-NLS-1$

+            return value != null ? ClassSpecificNameResolverRegistry.resolve(value) : null; 

+        }

+    }

 }

diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/FinalizerReferenceStatQuery.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/FinalizerReferenceStatQuery.java
index e208d53..62d2370 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/FinalizerReferenceStatQuery.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/FinalizerReferenceStatQuery.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008, 2010 SAP AG.

+ * Copyright (c) 2008, 2018 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -7,6 +7,7 @@
  *

  * Contributors:

  *    SAP AG - initial API and implementation

+ *    Andrew Johnson/IBM Corporation - only make query available with relevant classes

  *******************************************************************************/

 package org.eclipse.mat.inspections;

 

@@ -17,10 +18,12 @@
 import org.eclipse.mat.query.annotations.CommandName;

 import org.eclipse.mat.query.annotations.Icon;

 import org.eclipse.mat.snapshot.ISnapshot;

+import org.eclipse.mat.snapshot.extension.Subject;

 import org.eclipse.mat.util.IProgressListener;

 

 @CommandName("finalizer_references_statistics")

 @Icon("/META-INF/icons/finalizer.gif")

+@Subject("java.lang.ref.Finalizer")

 public class FinalizerReferenceStatQuery implements IQuery

 {

     @Argument

diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/FindStringsQuery.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/FindStringsQuery.java
index c51cadc..8d9ed79 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/FindStringsQuery.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/FindStringsQuery.java
@@ -42,8 +42,6 @@
 

     public IResult execute(IProgressListener listener) throws Exception

     {

-        listener.subTask(Messages.FindStringsQuery_SearchingStrings);

-

         ArrayInt result = new ArrayInt();

 

         Collection<IClass> classes = snapshot.getClassesByName("java.lang.String", false); //$NON-NLS-1$

@@ -54,6 +52,8 @@
                 {

                     int[] objectIds = clasz.getObjectIds();

 

+                    listener.beginTask(Messages.FindStringsQuery_SearchingStrings, objectIds.length);

+

                     for (int id : objectIds)

                     {

                         if (listener.isCanceled())

@@ -62,7 +62,11 @@
                         String value = snapshot.getObject(id).getClassSpecificName();

                         if (value != null && pattern.matcher(value).matches())

                             result.add(id);

+

+                        listener.worked(1);

                     }

+

+                    listener.done();

                 }

         }

         else

@@ -71,6 +75,14 @@
             {

                 IClass javaLangString = classes.iterator().next();

 

+                int totalWork = 0;

+                for (int[] objectIds : objects)

+                {

+                    totalWork += objectIds.length;

+                }

+

+                listener.beginTask(Messages.FindStringsQuery_SearchingStrings, totalWork);

+

                 ObjectsLoop: for (int[] objectIds : objects)

                 {

                     for (int id : objectIds)

@@ -91,8 +103,12 @@
                         {

                             result.add(id);

                         }

+

+                        listener.worked(1);

                     }

                 }

+

+                listener.done();

             }

         }

 

diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/PhantomReferenceStatQuery.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/PhantomReferenceStatQuery.java
index 5f1452c..1d31440 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/PhantomReferenceStatQuery.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/PhantomReferenceStatQuery.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2009, 2018 IBM Corporation and others.

+ * Copyright (c) 2009, 2019 IBM Corporation and others.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -18,10 +18,12 @@
 import org.eclipse.mat.query.annotations.CommandName;

 import org.eclipse.mat.query.annotations.Icon;

 import org.eclipse.mat.snapshot.ISnapshot;

+import org.eclipse.mat.snapshot.extension.Subject;

 import org.eclipse.mat.util.IProgressListener;

 

 @CommandName("phantom_references_statistics")

 @Icon("/META-INF/icons/phantom_reference.gif")

+@Subject("java.lang.ref.PhantomReference")

 public class PhantomReferenceStatQuery implements IQuery

 {

     @Argument

diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/SoftReferenceStatQuery.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/SoftReferenceStatQuery.java
index cd7526f..727179a 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/SoftReferenceStatQuery.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/SoftReferenceStatQuery.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008, 2018 SAP AG and IBM Corporation.

+ * Copyright (c) 2008, 2019 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -18,10 +18,12 @@
 import org.eclipse.mat.query.annotations.CommandName;

 import org.eclipse.mat.query.annotations.Icon;

 import org.eclipse.mat.snapshot.ISnapshot;

+import org.eclipse.mat.snapshot.extension.Subject;

 import org.eclipse.mat.util.IProgressListener;

 

 @CommandName("soft_references_statistics")

 @Icon("/META-INF/icons/soft_reference.gif")

+@Subject("java.lang.ref.SoftReference")

 public class SoftReferenceStatQuery implements IQuery

 {

     @Argument

diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/WeakReferenceStatQuery.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/WeakReferenceStatQuery.java
index 027e1d9..2ad991f 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/WeakReferenceStatQuery.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/WeakReferenceStatQuery.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2009, 2018 IBM Corporation.

+ * Copyright (c) 2009, 2019 IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -17,10 +17,12 @@
 import org.eclipse.mat.query.annotations.CommandName;

 import org.eclipse.mat.query.annotations.Icon;

 import org.eclipse.mat.snapshot.ISnapshot;

+import org.eclipse.mat.snapshot.extension.Subject;

 import org.eclipse.mat.util.IProgressListener;

 

 @CommandName("weak_references_statistics")

 @Icon("/META-INF/icons/weak_reference.gif")

+@Subject("java.lang.ref.WeakReference")

 public class WeakReferenceStatQuery implements IQuery

 {

     @Argument

diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/finalizer/annotations.properties b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/finalizer/annotations.properties
index 161faa3..b11ca80 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/finalizer/annotations.properties
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/inspections/finalizer/annotations.properties
@@ -29,7 +29,12 @@
 avoid finalizers. Long running tasks in the finalizer can block garbage \
 collection, because the memory can only be freed after the finalize method finished.\
 This query shows the the finalizer currently processed, the finalizer queue, \
-the demon finalizer thread or threads and the thread local variables.
+the demon finalizer thread or threads and the thread local variables.\n\n\
+Note: On J9 JVM-based dumps (e.g. IBM Java, OpenJ9), the Finalizer Queue list shows objects waiting \
+to be finalized and those which have already been finalized and are waiting to be \
+garbage collected. This query does not provide a way to differentiate the two \
+(because DTFJ doesn't), although you may be able to differentiate based on object \
+fields (e.g. a "closed" boolean field, etc.).
 
 FinalizerQueueQuery.name = Finalizer Queue
 FinalizerQueueQuery.help = Extract objects in the Finalizer Queue.\n\n\
@@ -41,7 +46,12 @@
 Be aware that there could be many reasons for a full finalizer queue: \
 the currently processed object could be blocking or long running \
 (please use our finalizer in processing query to check) or the application \
-made use of too many objects with finalize() which are queueing up in memory.
+made use of too many objects with finalize() which are queueing up in memory.\n\n\
+Note: On J9 JVM-based dumps (e.g. IBM Java, OpenJ9), this list shows objects waiting \
+to be finalized and those which have already been finalized and are waiting to be \
+garbage collected. This query does not provide a way to differentiate the two \
+(because DTFJ doesn't), although you may be able to differentiate based on object \
+fields (e.g. a "closed" boolean field, etc.).
 FinalizerQueueQuery.mode.help = Whether to display the objects as a list, histogram or both.
 
 FinalizerThreadLocalsQuery.name = Finalizer Thread Locals
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/FieldSizeArrayMapExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/FieldSizeArrayMapExtractor.java
new file mode 100644
index 0000000..1c2bd55
--- /dev/null
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/FieldSizeArrayMapExtractor.java
@@ -0,0 +1,116 @@
+/*******************************************************************************

+ * Copyright (c) 2019 IBM Corporation and others

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    IBM Corporation - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.mat.internal.collectionextract;

+

+import java.util.Iterator;

+import java.util.Map;

+import java.util.Map.Entry;

+import java.util.NoSuchElementException;

+

+import org.eclipse.mat.SnapshotException;

+import org.eclipse.mat.inspections.collectionextract.IMapExtractor;

+import org.eclipse.mat.snapshot.ISnapshot;

+import org.eclipse.mat.snapshot.model.IObject;

+import org.eclipse.mat.snapshot.model.IObjectArray;

+

+public class FieldSizeArrayMapExtractor extends FieldSizeArrayCollectionExtractor implements IMapExtractor

+{

+    FieldArrayCollectionExtractor keysExtractor;

+    public FieldSizeArrayMapExtractor(String sizeField, String valuesArrayField, String keysCollectionField)

+    {

+        super(sizeField, valuesArrayField);

+        keysExtractor = new FieldArrayCollectionExtractor(keysCollectionField);

+    }

+

+    public boolean hasCollisionRatio()

+    {

+        return true;

+    }

+

+    public Double getCollisionRatio(IObject collection) throws SnapshotException

+    {

+        return 0.0;

+    }

+

+    public Iterator<Entry<IObject, IObject>> extractMapEntries(IObject collection) throws SnapshotException

+    {

+        final IObjectArray valueArray = extractEntries(collection);

+        final IObjectArray keyArray = keysExtractor.extractEntries(collection);

+        final ISnapshot snapshot = collection.getSnapshot();

+        return new Iterator<Entry<IObject, IObject>>() {

+            int ix = 0;

+            public boolean hasNext()

+            {

+                while (ix < valueArray.getLength())

+                {

+                    if (valueArray.getReferenceArray(ix, 1)[0] != 0)

+                        return true;

+                    ++ix;

+                }

+                return false;

+            }

+

+            public Map.Entry<IObject, IObject> next()

+            {

+                if (hasNext())

+                {

+                    final int ix2 = ix++;

+                    final IObject key, value;

+                    long keyaddr = keyArray.getReferenceArray(ix2, 1)[0];

+                    try

+                    {

+                        int keyid = snapshot.mapAddressToId(keyaddr);

+                        key = snapshot.getObject(keyid);

+                    }

+                    catch (SnapshotException e)

+                    {

+                        NoSuchElementException ise = new NoSuchElementException();

+                        ise.initCause(e);

+                        throw ise;

+                    }

+

+                    long valueaddr = valueArray.getReferenceArray(ix2, 1)[0];

+                    try

+                    {

+                        int valueid = snapshot.mapAddressToId(valueaddr);

+                        value = snapshot.getObject(valueid);

+                    }

+                    catch (SnapshotException e)

+                    {

+                        NoSuchElementException ise = new NoSuchElementException();

+                        ise.initCause(e);

+                        throw ise;

+                    }

+                    return new Map.Entry<IObject, IObject>() {

+

+                        public IObject getKey()

+                        {

+                            return key;

+                        }

+

+                        public IObject getValue()

+                        {

+                            return value;

+                        }

+

+                        public IObject setValue(IObject value)

+                        {

+                            throw new UnsupportedOperationException();

+                        }

+

+                    };

+                }

+                throw new NoSuchElementException();

+            }

+            

+        };

+    }

+}

diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java
index 81aac22..07e5ec5 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/KnownCollectionInfo.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others
+ * Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -50,7 +50,7 @@
                     new CollectionExtractionInfo("java.util.concurrent.ConcurrentLinkedBlockingQueue", new LinkedListCollectionExtractor("count.value", "head.next")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                     new CollectionExtractionInfo("java.util.concurrent.LinkedBlockingDeque", new LinkedListCollectionExtractor("count", "first.next")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                     new CollectionExtractionInfo("java.util.concurrent.LinkedBlockingQueue", new LinkedListCollectionExtractor("count.value", "head.next")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-                    new CollectionExtractionInfo("java.util.concurrent.ArrayBlockingQueue", new IBM6ArrayListCollectionExtractor("takeIndex", "putIndex", "items", "count")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NONO-NLS-4$
+                    new CollectionExtractionInfo("java.util.concurrent.ArrayBlockingQueue", new IBM6ArrayListCollectionExtractor("takeIndex", "putIndex", "items", "count")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
 
                     // these store the data in an array
                     new CollectionExtractionInfo("java.util.concurrent.CopyOnWriteArrayList", new FieldArrayCollectionExtractor("array")), // //$NON-NLS-1$ //$NON-NLS-2$
@@ -68,6 +68,8 @@
                     new CollectionExtractionInfo("java.util.PriorityQueue", JdkVersion.of(IBM15, IBM16), new FieldSizeArrayCollectionExtractor("size", "elements")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                     new CollectionExtractionInfo("java.util.concurrent.DelayQueue", JdkVersion.except(IBM15, IBM16), new FieldSizeArrayCollectionExtractor("q.size", "q.queue")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                     new CollectionExtractionInfo("java.util.concurrent.DelayQueue", JdkVersion.of(IBM15, IBM16), new FieldSizeArrayCollectionExtractor("q.size", "q.elements")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                    new CollectionExtractionInfo("java.util.concurrent.PriorityBlockingQueue", new FieldSizeArrayCollectionExtractor("size", "queue")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                    new CollectionExtractionInfo("java.util.concurrent.PriorityBlockingDeque", new FieldSizeArrayCollectionExtractor("size", "queue")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
                     // The length of the array is the size
                     new CollectionExtractionInfo("java.util.Arrays$ArrayList", new FieldSizeArrayCollectionExtractor("a.@length", "a")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@@ -83,14 +85,17 @@
                     new CollectionExtractionInfo("java.util.IdentityHashMap", IBM16, new IdentityHashMapCollectionExtractor("size", "elementData")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                     new CollectionExtractionInfo("java.util.IdentityHashMap$KeySet", new KeySetCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("java.util.IdentityHashMap$Values", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.IdentityHashMap$EntrySet", new WrapperMapExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
 
                     // hash maps
                     new CollectionExtractionInfo("java.util.HashMap", JdkVersion.except(IBM16), new HashMapCollectionExtractor("size", "table", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
                     new CollectionExtractionInfo("java.util.HashMap", IBM16, new HashMapCollectionExtractor("elementCount", "elementData", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
                     new CollectionExtractionInfo("java.util.HashMap$KeySet", new KeySetCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("java.util.HashMap$Values", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.HashMap$EntrySet", new WrapperMapExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("java.util.LinkedHashMap$LinkedKeySet", new KeySetCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("java.util.LinkedHashMap$LinkedValues", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.LinkedHashMap$LinkedEntrySet", new WrapperMapExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
 
                     // Some Java 5 PHD files don't have superclass info so add
                     // LinkedHashMap to list
@@ -112,6 +117,7 @@
                     new CollectionExtractionInfo("javax.script.SimpleBindings", IBM16, // //$NON-NLS-1$
                                     new HashMapCollectionExtractor(
                                                     "map.elementCount", "map.elementData", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+                    new CollectionExtractionInfo("javax.management.openmbean.TabularDataSupport", new WrapperMapExtractor("dataMap")), // //$NON-NLS-1$ //$NON-NLS-2$
 
                     new CollectionExtractionInfo("java.util.jar.Attributes", JdkVersion.except(IBM16), new HashMapCollectionExtractor("map.size", "map.table", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
                     new CollectionExtractionInfo("java.util.jar.Attributes", IBM16, // //$NON-NLS-1$
@@ -131,6 +137,7 @@
                                     new HashMapCollectionExtractor("elementCount", "elementData", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
                     new CollectionExtractionInfo("java.util.Hashtable$KeySet", new KeySetCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("java.util.Hashtable$ValueCollection", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.Hashtable$EntrySet", new WrapperMapExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
 
                     // Some Java 5 PHD files don't have superclass info so add
                     // Properties to list
@@ -142,10 +149,12 @@
                     new CollectionExtractionInfo("java.util.WeakHashMap", IBM16, new HashMapCollectionExtractor("elementCount", "elementData", "referent", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
                     new CollectionExtractionInfo("java.util.WeakHashMap$KeySet", new KeySetCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("java.util.WeakHashMap$Values", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.WeakHashMap$EntrySet", new WrapperMapExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("sun.awt.WeakIdentityHashMap",  new HashMapCollectionExtractor("map.size", "map.table", "key.referent", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
 
                     new CollectionExtractionInfo("java.lang.ThreadLocal$ThreadLocalMap", // //$NON-NLS-1$
                                     new HashMapCollectionExtractor("size", "table", "referent", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+                    new CollectionExtractionInfo("java.lang.ProcessEnvironment$CheckedEntrySet", new WrapperMapExtractor("s")), //$NON-NLS-1$ //$NON-NLS-2$
 
                     new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap$Segment", new HashMapCollectionExtractor("count", "table", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
 
@@ -153,15 +162,17 @@
                     // small maps.
                     new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap", JdkVersion.of(JAVA18, IBM18, JAVA19, IBM19), new HashMapCollectionExtractor("baseCount", "table", "key", "val")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
                     new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap", JdkVersion.except(JAVA18, IBM18, JAVA19, IBM19), new ConcurrentHashMapCollectionExtractor("segments", "key", "value")), // //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap$KeySetView", new KeySetCollectionExtractor("map")),
-                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap$ValuesView", new ValuesCollectionExtractor("map")),
+                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap$KeySetView", new KeySetCollectionExtractor("map")), //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap$ValuesView", new ValuesCollectionExtractor("map")), //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentHashMap$EntrySetView", new WrapperMapExtractor("map")), //$NON-NLS-1$ //$NON-NLS-2$
 
                     new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListSet", //$NON-NLS-1$
-                                    new ConcurrentSkipListSetCollectionExtractor("m.head.node", "key", "value")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                                    new KeySetCollectionExtractor("m")), //$NON-NLS-1$
                     new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListMap", //$NON-NLS-1$
                                     new ConcurrentSkipListCollectionExtractor("head.node", "key", "value")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListMap$KeySet", new KeySetCollectionExtractor("map")),
-                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListMap$Values", new ValuesCollectionExtractor("map")),
+                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListMap$KeySet", new KeySetCollectionExtractor("m")), //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListMap$Values", new ValuesCollectionExtractor("m")), //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.concurrent.ConcurrentSkipListMap$EntrySet", new WrapperMapExtractor("m")), //$NON-NLS-1$ //$NON-NLS-2$
 
                     // tree maps
                     new CollectionExtractionInfo("java.util.TreeMap", JdkVersion.except(IBM16), new TreeMapCollectionExtractor("size", "key", "value")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
@@ -170,6 +181,7 @@
                     new CollectionExtractionInfo("java.util.TreeSet", IBM16, new TreeSetCollectionExtractor("backingMap.size", "keys[]", "values[]")), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
                     new CollectionExtractionInfo("java.util.TreeMap$KeySet", new KeySetCollectionExtractor("m")), // //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("java.util.TreeMap$Values", new ValuesCollectionExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.TreeMap$EntrySet", new WrapperMapExtractor("this$0")), // //$NON-NLS-1$ //$NON-NLS-2$
 
                     // wrappers
                     // also works for SynchronizedSet, SynchronizedSortedSet,
@@ -191,10 +203,12 @@
                     new CollectionExtractionInfo("java.util.Collections$CheckedCollection", new WrapperCollectionExtractor("c")), //$NON-NLS-1$ //$NON-NLS-2$
                     // also works for CheckedSortedMap
                     new CollectionExtractionInfo("java.util.Collections$CheckedMap", new WrapperMapExtractor("m")), //$NON-NLS-1$ //$NON-NLS-2$
-                    new CollectionExtractionInfo("java.util.Collections$CheckedMap$CheckedEntrySet", new WrapperCollectionExtractor("s")), //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.Collections$CheckedMap$CheckedEntrySet", new WrapperMapExtractor("s")), //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.Collections$SetFromMap", new KeySetCollectionExtractor("m")), //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("org.eclipse.osgi.framework.util.CaseInsensitiveDictionaryMap", new WrapperMapExtractor("map")), //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("org.eclipse.osgi.framework.util.CaseInsensitiveDictionaryMap$KeySet", new KeySetCollectionExtractor("this$0")),  //$NON-NLS-1$ //$NON-NLS-2$
-                    new CollectionExtractionInfo("org.eclipse.osgi.framework.util.CaseInsensitiveDictionaryMap$Values", new ValuesCollectionExtractor("this$0")),  //$NON-NLS-1$ //$NON-NLS-2$ 
+                    new CollectionExtractionInfo("org.eclipse.osgi.framework.util.CaseInsensitiveDictionaryMap$Values", new ValuesCollectionExtractor("this$0")),  //$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("org.eclipse.osgi.framework.util.CaseInsensitiveDictionaryMap$EntrySet", new WrapperMapExtractor("this$0")),  //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("java.awt.RenderingHints", new WrapperMapExtractor("hintmap")), //$NON-NLS-1$ //$NON-NLS-2$
 
                     // singletons
@@ -203,6 +217,12 @@
                     new CollectionExtractionInfo("java.util.Collections$SingletonMap", new SingletonMapExtractor("k", "v")),//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                     new CollectionExtractionInfo("java.util.Collections$CopiesList", new ReplicatedValueCollectionExtractor("n", "element")),//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
+                    // Enum maps/sets
+                    new CollectionExtractionInfo("java.util.EnumMap", new FieldSizeArrayMapExtractor("size", "vals", "keyUniverse")),//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+                    new CollectionExtractionInfo("java.util.EnumMap$Values", new ValuesCollectionExtractor("this$0")),//$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.EnumMap$KeySet", new KeySetCollectionExtractor("this$0")),//$NON-NLS-1$ //$NON-NLS-2$
+                    new CollectionExtractionInfo("java.util.RegularEnumSet", new RegularEnumSetExtractor("elements", "Universe")),//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
                     // New Java 9 collections
                     new CollectionExtractionInfo("java.util.ImmutableCollections$Set1", new SingletonCollectionExtractor("e0")), //$NON-NLS-1$ //$NON-NLS-2$
                     new CollectionExtractionInfo("java.util.ImmutableCollections$List1", new SingletonCollectionExtractor("e0")), //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/LinkedListCollectionExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/LinkedListCollectionExtractor.java
index a4c2f78..f3e2592 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/LinkedListCollectionExtractor.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/LinkedListCollectionExtractor.java
@@ -62,7 +62,7 @@
             header = ExtractionUtils.followOnlyOutgoingReferencesExceptLast(leadField, list);
         }
         if (header == null)
-            return null;
+            return new int[0];
 
         IObject previous = header;
         IObject current = header;
@@ -177,7 +177,7 @@
         int entries[] =  extractEntryIds(coll);
         if (entries == null)
             return 0;
-        else 
+        else
             return entries.length;
     }
 }
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/RegularEnumSetExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/RegularEnumSetExtractor.java
new file mode 100644
index 0000000..77203aa
--- /dev/null
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/RegularEnumSetExtractor.java
@@ -0,0 +1,118 @@
+/*******************************************************************************

+ * Copyright (c) 2019 IBM Corporation

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    IBM Corporation - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.mat.internal.collectionextract;

+

+import java.util.Iterator;

+import java.util.Map.Entry;

+

+import org.eclipse.mat.SnapshotException;

+import org.eclipse.mat.collect.ArrayInt;

+import org.eclipse.mat.inspections.collectionextract.IMapExtractor;

+import org.eclipse.mat.snapshot.ISnapshot;

+import org.eclipse.mat.snapshot.model.IObject;

+

+public class RegularEnumSetExtractor extends FieldSizeArrayCollectionExtractor implements IMapExtractor

+{

+

+    /**

+     * For java.util.RegularEnumSet

+     * @param sizeField - holds the bits indicating which set items are used

+     * @param arrayField - all the enum values

+     */

+    public RegularEnumSetExtractor(String sizeField, String arrayField)

+    {

+        super(sizeField, arrayField);

+    }

+

+    public Integer getSize(IObject coll) throws SnapshotException

+    {

+        Object o = coll.resolveValue(sizeField);

+        if (o instanceof Number)

+        {

+            return Long.bitCount(((Number)o).longValue());

+        }

+        return null;

+    }

+

+    public int[] extractEntryIds(IObject coll) throws SnapshotException

+    {

+        Object o = coll.resolveValue(sizeField);

+        long used = 0;

+        if (o instanceof Number)

+        {

+            used = ((Number)o).longValue();

+        }

+

+        ArrayInt arr = new ArrayInt();

+        long referenceArray[] = extractEntries(coll).getReferenceArray();

+        ISnapshot snapshot = coll.getSnapshot();

+        for (int i = 0; i < referenceArray.length && used != 0; i++)

+        {

+            if (referenceArray[i] != 0 && (used & 1) != 0)

+                arr.add(snapshot.mapAddressToId(referenceArray[i]));

+        }

+        return arr.toArray();

+    }

+

+    public boolean hasCollisionRatio()

+    {

+        return true;

+    }

+

+    public Double getCollisionRatio(IObject collection) throws SnapshotException

+    {

+        return 0.0;

+    }

+

+    public Iterator<Entry<IObject, IObject>> extractMapEntries(IObject collection) throws SnapshotException

+    {

+        final ISnapshot snapshot = collection.getSnapshot();

+        final int[] ids = extractEntryIds(collection);

+        return new Iterator<Entry<IObject, IObject>>() {

+            int ix = 0;

+            public boolean hasNext()

+            {

+                return ix < ids.length;

+            }

+

+            public Entry<IObject, IObject> next()

+            {

+                final IObject o;

+                try

+                {

+                    o = snapshot.getObject(ids[ix++]);

+                }

+                catch (SnapshotException e)

+                {

+                    throw new RuntimeException(e);

+                }

+                return new Entry<IObject, IObject>() {

+

+                    public IObject getKey()

+                    {

+                        return o;

+                    }

+

+                    public IObject getValue()

+                    {

+                        return o;

+                    }

+

+                    public IObject setValue(IObject value)

+                    {

+                        throw new UnsupportedOperationException();

+                    }

+

+                };

+            }

+        };

+    }

+}

diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/WrapperCollectionExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/WrapperCollectionExtractor.java
index 57dae61..fc8fc5f 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/WrapperCollectionExtractor.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/WrapperCollectionExtractor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others
+ * Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -99,13 +99,29 @@
         return extractList(coll).getNumberOfNotNullElements();
     }
 
+    private String desc(String msg, IObject coll, AbstractExtractedCollection<?, ?> ec)
+    {
+        if (ec != null)
+            return msg + coll.getDisplayName() + "; " + ec.getDisplayName(); //$NON-NLS-1$
+        try
+        {
+            Object coll2 = coll.resolveValue(field);
+            if (coll2 instanceof IObject)
+                return msg + coll.getDisplayName() + "; " + ((IObject)coll2).getDisplayName(); //$NON-NLS-1$
+        }
+        catch (SnapshotException e)
+        {
+        }
+        return msg + coll.getDisplayName();
+    }
+
     protected ExtractedCollection extractList(IObject coll)
     {
         AbstractExtractedCollection<?, ?> ec = extractCollection(coll);
         if (ec instanceof ExtractedCollection)
             return (ExtractedCollection) ec;
         else
-            throw new UnsupportedOperationException("not a list-ish collection: " + coll.getDisplayName() + (ec != null ? ("; " + ec.getDisplayName()) : ""));
+            throw new UnsupportedOperationException(desc("not a list-ish collection: ", coll, ec));
     }
 
     protected ExtractedMap extractMap(IObject coll)
@@ -114,7 +130,7 @@
         if (ec instanceof ExtractedMap)
             return (ExtractedMap) ec;
         else
-            throw new UnsupportedOperationException("not a map: " + coll.getDisplayName() + (ec != null ? ("; " + ec.getDisplayName()) : ""));
+            throw new UnsupportedOperationException(desc("not a map: ", coll, ec));
     }
 
     protected AbstractExtractedCollection<?, ?> extractCollection(IObject coll)
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/WrapperSetFromMapExtractor.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/WrapperSetFromMapExtractor.java
new file mode 100644
index 0000000..e7a865a
--- /dev/null
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/collectionextract/WrapperSetFromMapExtractor.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2019 IBM Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mat.internal.collectionextract;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.inspections.collectionextract.IMapExtractor;
+import org.eclipse.mat.snapshot.model.IObject;
+
+/**
+ * Creates an extractor to view a map as a set.
+ * Just treating it as a map does not work as extractEntryIds needs to return the keys,
+ * not the nodes of type Map.Entry.
+ *
+ */
+public class WrapperSetFromMapExtractor extends WrapperCollectionExtractor implements IMapExtractor
+{
+    WrapperMapExtractor mapext;
+    public WrapperSetFromMapExtractor(String setField, String mapField)
+    {
+        super(setField);
+        mapext = new WrapperMapExtractor(mapField);
+    }
+
+    public boolean hasCollisionRatio()
+    {
+        return mapext.hasCollisionRatio();
+    }
+
+    public Double getCollisionRatio(IObject collection) throws SnapshotException
+    {
+        return mapext.getCollisionRatio(collection);
+    }
+
+    public Iterator<Entry<IObject, IObject>> extractMapEntries(IObject collection) throws SnapshotException
+    {
+        return mapext.extractMapEntries(collection);
+    }
+
+}
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/snapshot/inspections/DominatorQuery.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/snapshot/inspections/DominatorQuery.java
index 1b7b22a..3343e28 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/snapshot/inspections/DominatorQuery.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/snapshot/inspections/DominatorQuery.java
@@ -658,11 +658,11 @@
             NumberFormat nf = NumberFormat.getPercentInstance();

             nf.setMinimumFractionDigits(2);

             nf.setMaximumFractionDigits(2);

-            return new Column[] { new Column(Messages.Column_ClassLoaderName, String.class), //

-                            new Column(Messages.Column_Objects, int.class), //

-                            new Column(Messages.Column_ShallowHeap, Bytes.class), //

-                            new Column(Messages.Column_RetainedHeap, Bytes.class).sorting(SortDirection.DESC), //

-                            new Column(Messages.Column_Percentage, double.class).formatting(nf) }; //$NON-NLS-1$

+            return new Column[] { new Column(Messages.Column_ClassLoaderName, String.class),

+                            new Column(Messages.Column_Objects, int.class),

+                            new Column(Messages.Column_ShallowHeap, Bytes.class),

+                            new Column(Messages.Column_RetainedHeap, Bytes.class).sorting(SortDirection.DESC),

+                            new Column(Messages.Column_Percentage, double.class).formatting(nf) };

         }

 

         public List<?> getElements()

diff --git a/plugins/org.eclipse.mat.chart.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.chart.ui/META-INF/MANIFEST.MF
index 4ca70f9..7b70cd1 100644
--- a/plugins/org.eclipse.mat.chart.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.chart.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: %Bundle-Name

 Bundle-SymbolicName: org.eclipse.mat.chart.ui;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-Vendor: %Bundle-Vendor

 Require-Bundle: org.eclipse.mat.chart;bundle-version="1.0.0",

  org.eclipse.mat.ui;bundle-version="1.0.0",

diff --git a/plugins/org.eclipse.mat.chart.ui/pom.xml b/plugins/org.eclipse.mat.chart.ui/pom.xml
index 81fef0d..6610d5e 100644
--- a/plugins/org.eclipse.mat.chart.ui/pom.xml
+++ b/plugins/org.eclipse.mat.chart.ui/pom.xml
Binary files differ
diff --git a/plugins/org.eclipse.mat.chart/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.chart/META-INF/MANIFEST.MF
index a50df5b..39cab92 100644
--- a/plugins/org.eclipse.mat.chart/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.chart/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: %Bundle-Name

 Bundle-SymbolicName: org.eclipse.mat.chart;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Require-Bundle: org.eclipse.mat.api;bundle-version="1.0.0",

  org.eclipse.birt.chart.engine;bundle-version="2.3.0"

 Export-Package: org.eclipse.mat.impl.chart;x-friends:="org.eclipse.mat.chart.ui"

diff --git a/plugins/org.eclipse.mat.chart/about.mappings b/plugins/org.eclipse.mat.chart/about.mappings
index 5b4a719..971fdee 100644
--- a/plugins/org.eclipse.mat.chart/about.mappings
+++ b/plugins/org.eclipse.mat.chart/about.mappings
@@ -9,4 +9,4 @@
 #*    IBM Corporation - initial API and implementation and/or initial documentation

 #*******************************************************************************

 #Build

-0=1.8.1

+0=1.9.1

diff --git a/plugins/org.eclipse.mat.chart/about.properties b/plugins/org.eclipse.mat.chart/about.properties
index bed8042..c849e33 100644
--- a/plugins/org.eclipse.mat.chart/about.properties
+++ b/plugins/org.eclipse.mat.chart/about.properties
@@ -1,5 +1,5 @@
 h#*******************************************************************************
-#* Copyright (c) 2010, 2017 IBM Corporation.
+#* Copyright (c) 2010, 2019 IBM Corporation.
 #* All rights reserved. This program and the accompanying materials
 #* are made available under the terms of the Eclipse Public License v1.0
 #* which accompanies this distribution, and is available at
@@ -13,7 +13,7 @@
 Version: {featureVersion}\n\
 Build id: {0}\n\
 \n\
-Copyright (c) 2008, 2017 SAP AG, IBM Corporation and others.\n\
+Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.\n\
 All rights reserved. This program and the accompanying materials\n\
 are made available under the terms of the Eclipse Public License v1.0\n\
 which accompanies this distribution, and is available at\n\
diff --git a/plugins/org.eclipse.mat.chart/pom.xml b/plugins/org.eclipse.mat.chart/pom.xml
index 440975e..3fd6e6d 100644
--- a/plugins/org.eclipse.mat.chart/pom.xml
+++ b/plugins/org.eclipse.mat.chart/pom.xml
@@ -9,7 +9,7 @@
     <groupId>org.eclipse.mat</groupId>

     <artifactId>parent</artifactId>

     <relativePath>../../parent</relativePath>

-    <version>1.8.1-SNAPSHOT</version>

+    <version>1.9.1-SNAPSHOT</version>

   </parent>

 

   <artifactId>org.eclipse.mat.chart</artifactId>

diff --git a/plugins/org.eclipse.mat.dtfj/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.dtfj/META-INF/MANIFEST.MF
index 28081bf..49fb4ea 100644
--- a/plugins/org.eclipse.mat.dtfj/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.dtfj/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-SymbolicName: org.eclipse.mat.dtfj;singleton:=true

 Bundle-Name: %Bundle-Name

 Bundle-Vendor: %Bundle-Vendor

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-RequiredExecutionEnvironment: J2SE-1.5

 Require-Bundle: org.eclipse.mat.parser;bundle-version="1.0.0",

  org.eclipse.core.runtime;bundle-version="3.3.100",

diff --git a/plugins/org.eclipse.mat.dtfj/pom.xml b/plugins/org.eclipse.mat.dtfj/pom.xml
index 03b20ec..c7e243e 100644
--- a/plugins/org.eclipse.mat.dtfj/pom.xml
+++ b/plugins/org.eclipse.mat.dtfj/pom.xml
@@ -9,7 +9,7 @@
     <groupId>org.eclipse.mat</groupId>

     <artifactId>parent</artifactId>

     <relativePath>../../parent</relativePath>

-    <version>1.8.1-SNAPSHOT</version>

+    <version>1.9.1-SNAPSHOT</version>

   </parent>

 

   <artifactId>org.eclipse.mat.dtfj</artifactId>

diff --git a/plugins/org.eclipse.mat.hprof/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.hprof/META-INF/MANIFEST.MF
index 8a51616..667aa45 100644
--- a/plugins/org.eclipse.mat.hprof/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.hprof/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: %Bundle-Name

 Bundle-SymbolicName: org.eclipse.mat.hprof;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-Vendor: %Bundle-Vendor

 Require-Bundle: org.eclipse.mat.parser;bundle-version="1.0.0",

  org.eclipse.core.runtime;bundle-version="3.3.100",

diff --git a/plugins/org.eclipse.mat.hprof/pom.xml b/plugins/org.eclipse.mat.hprof/pom.xml
index fe50bb3..5a4bca6 100644
--- a/plugins/org.eclipse.mat.hprof/pom.xml
+++ b/plugins/org.eclipse.mat.hprof/pom.xml
Binary files differ
diff --git a/plugins/org.eclipse.mat.ibmdumps/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.ibmdumps/META-INF/MANIFEST.MF
index b506172..6c60f35 100644
--- a/plugins/org.eclipse.mat.ibmdumps/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.ibmdumps/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-SymbolicName: org.eclipse.mat.ibmdumps;singleton:=true

 Bundle-Name: %Bundle-Name

 Bundle-Vendor: %Bundle-Vendor

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Require-Bundle: org.eclipse.core.runtime;bundle-version="3.3.100",

  org.eclipse.mat.api;bundle-version="1.0.0"

 Bundle-RequiredExecutionEnvironment: J2SE-1.5

diff --git a/plugins/org.eclipse.mat.ibmdumps/pom.xml b/plugins/org.eclipse.mat.ibmdumps/pom.xml
index 7e494be..002017b 100644
--- a/plugins/org.eclipse.mat.ibmdumps/pom.xml
+++ b/plugins/org.eclipse.mat.ibmdumps/pom.xml
@@ -9,7 +9,7 @@
     <groupId>org.eclipse.mat</groupId>

     <artifactId>parent</artifactId>

     <relativePath>../../parent</relativePath>

-    <version>1.8.1-SNAPSHOT</version>

+    <version>1.9.1-SNAPSHOT</version>

   </parent>

 

   <artifactId>org.eclipse.mat.ibmdumps</artifactId>

diff --git a/plugins/org.eclipse.mat.jdt/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.jdt/META-INF/MANIFEST.MF
index b0dd49f..ebe1728 100644
--- a/plugins/org.eclipse.mat.jdt/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.jdt/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: %Bundle-Name

 Bundle-SymbolicName: org.eclipse.mat.jdt;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-RequiredExecutionEnvironment: J2SE-1.5

 Require-Bundle: org.eclipse.mat.api;bundle-version="1.0.0",

  org.eclipse.ui,

diff --git a/plugins/org.eclipse.mat.jdt/pom.xml b/plugins/org.eclipse.mat.jdt/pom.xml
index f43650f..35f6530 100644
--- a/plugins/org.eclipse.mat.jdt/pom.xml
+++ b/plugins/org.eclipse.mat.jdt/pom.xml
@@ -9,7 +9,7 @@
     <groupId>org.eclipse.mat</groupId>

     <artifactId>parent</artifactId>

     <relativePath>../../parent</relativePath>

-    <version>1.8.1-SNAPSHOT</version>

+    <version>1.9.1-SNAPSHOT</version>

   </parent>

 

   <artifactId>org.eclipse.mat.jdt</artifactId>

diff --git a/plugins/org.eclipse.mat.jruby.resolver/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.jruby.resolver/META-INF/MANIFEST.MF
index a72cc69..56ba1e7 100644
--- a/plugins/org.eclipse.mat.jruby.resolver/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.jruby.resolver/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: %Bundle-Name

 Bundle-SymbolicName: org.eclipse.mat.jruby.resolver;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-Vendor: %Bundle-Vendor

 Bundle-RequiredExecutionEnvironment: J2SE-1.5

 Require-Bundle: org.eclipse.mat.api;bundle-version="[1.0.0,2.0.0)",

diff --git a/plugins/org.eclipse.mat.jruby.resolver/pom.xml b/plugins/org.eclipse.mat.jruby.resolver/pom.xml
index deb858e..3927214 100644
--- a/plugins/org.eclipse.mat.jruby.resolver/pom.xml
+++ b/plugins/org.eclipse.mat.jruby.resolver/pom.xml
Binary files differ
diff --git a/plugins/org.eclipse.mat.parser/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.parser/META-INF/MANIFEST.MF
index c97a64d..a0a2782 100644
--- a/plugins/org.eclipse.mat.parser/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.parser/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: %Bundle-Name

 Bundle-SymbolicName: org.eclipse.mat.parser;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-Activator: org.eclipse.mat.parser.internal.ParserPlugin

 Bundle-Vendor: %Bundle-Vendor

 Require-Bundle: org.eclipse.core.runtime;bundle-version="3.3.100",

diff --git a/plugins/org.eclipse.mat.parser/pom.xml b/plugins/org.eclipse.mat.parser/pom.xml
index 4ed9f89..641bbe6 100644
--- a/plugins/org.eclipse.mat.parser/pom.xml
+++ b/plugins/org.eclipse.mat.parser/pom.xml
Binary files differ
diff --git a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/Messages.java b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/Messages.java
index a517c2a..4af0c8e 100644
--- a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/Messages.java
+++ b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/Messages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2009, 2011 SAP AG and IBM Corporation.

+ * Copyright (c) 2009, 2019 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -91,6 +91,9 @@
     public static String SnapshotImpl_RetrievingDominators;

     public static String ObjectArrayImpl_forArray;

     public static String ObjectMarker_MarkingObjects;

+    public static String ObjectMarker_ErrorMarkingObjects;

+    public static String ObjectMarker_WarningMarkingObjects;

+    public static String ObjectMarker_ErrorMarkingObjectsSeeLog;

     public static String Operation_Error_ArgumentOfUnknownClass;

     public static String Operation_Error_CannotCompare;

     public static String Operation_Error_NotInArgumentOfUnknownClass;

diff --git a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/messages.properties b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/messages.properties
index 11f70fe..eab5fa0 100644
--- a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/messages.properties
+++ b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/messages.properties
@@ -1,5 +1,5 @@
 ###############################################################################

-# Copyright (c) 2008, 2011 SAP AG and others.

+# Copyright (c) 2008, 2019 SAP AG and others.

 # All rights reserved. This program and the accompanying materials

 # are made available under the terms of the Eclipse Public License v1.0

 # which accompanies this distribution, and is available at

@@ -84,6 +84,9 @@
 SnapshotImpl_RetrievingDominators=Retrieving dominators...

 ObjectArrayImpl_forArray={0} for array {1}

 ObjectMarker_MarkingObjects=Marking reachable objects

+ObjectMarker_ErrorMarkingObjects=Error marking reachable objects

+ObjectMarker_WarningMarkingObjects=Out of memory error while marking reachable objects, continuing with remaining threads

+ObjectMarker_ErrorMarkingObjectsSeeLog={0} errors marking reachable objects, check the error log for further details

 Operation_Error_ArgumentOfUnknownClass=right argument to IN of unknown class {0}

 Operation_Error_CannotCompare=IN: cannot compare left argument of type {0} to int[]

 Operation_Error_NotInArgumentOfUnknownClass=right argument to NOT IN of unknown class {0}

diff --git a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/snapshot/ObjectMarker.java b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/snapshot/ObjectMarker.java
index b69bd06..73de1cb 100644
--- a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/snapshot/ObjectMarker.java
+++ b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/snapshot/ObjectMarker.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008, 2013 SAP AG and IBM Corporation.

+ * Copyright (c) 2008, 2019 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -29,6 +29,8 @@
 import org.eclipse.mat.snapshot.model.IObject;

 import org.eclipse.mat.snapshot.model.NamedReference;

 import org.eclipse.mat.util.IProgressListener;

+import org.eclipse.mat.util.MessageUtil;

+import org.eclipse.mat.util.IProgressListener.Severity;

 

 public class ObjectMarker

 {

@@ -360,8 +362,13 @@
                 push(z);

                 ++pushed;

                 if (waitingThreads > 0)

+                {

                     // All or one?

-                    notifyAll();

+                    if (size() > 1)

+                        notifyAll();

+                    else

+                        notify();

+                }

                 return true;

             }

             return false;

@@ -421,14 +428,30 @@
         }

 

         // wait for all the threads to finish

+        

+        int failed = 0;

+        Throwable failure = null;

         for (int i = 0; i < numberOfThreads; i++)

         {

             threads[i].join();

+            if (!dfsthreads[i].completed)

+            {

+                ++failed;

+                if (failure == null)

+                {

+                    failure = dfsthreads[i].failure;

+                }

+            }

         }

 

         if (progressListener.isCanceled())

             return;

 

+        if (failed > 0)

+        {

+            throw new RuntimeException(MessageUtil.format(Messages.ObjectMarker_ErrorMarkingObjectsSeeLog, failed), failure);

+        }

+

         progressListener.done();

         if (DEBUG) System.out.println("Took "+(System.currentTimeMillis() - l)+"ms"); //$NON-NLS-1$//$NON-NLS-2$

     }

@@ -436,9 +459,12 @@
     public class DfsThread implements Runnable

     {

 

+        boolean completed; // normal completion

         int size = 0;

         int[] data = new int[10 * 1024]; // start with 10k

         IntStack rootsStack;

+        int current = -1;

+        Throwable failure; // Exception/Error

 

         public DfsThread(IntStack roots)

         {

@@ -447,58 +473,70 @@
 

         public void run()

         {

-            while (true)

+            try

             {

-                synchronized (rootsStack)

+                while (true)

                 {

-                    progressListener.worked(1);

-                    if (progressListener.isCanceled())

-                        return;

-

-                    if (rootsStack.size() > 0) // still some roots are not

-                    // processed

+                    synchronized (rootsStack)

                     {

-                        data[0] = rootsStack.pop();

-                        size = 1;

-                    }

-                    else

-                    // the work is done

-                    {

-                        break;

-                    }

-                }

+                        progressListener.worked(1);

+                        if (progressListener.isCanceled())

+                            return;

 

-                int current;

-

-                while (size > 0)

-                {

-                    /* start stack.pop() */

-                    current = data[--size];

-                    /* end stack.pop */

-

-                    for (int child : outbound.get(current))

-                    {

-                        /*

-                         * No synchronization here. It costs a lot of

-                         * performance It is possible that some bits are marked

-                         * more than once, but this is not a problem

-                         */

-                        if (!bits[child])

+                        if (rootsStack.size() > 0) // still some roots are not

+                            // processed

                         {

-                            bits[child] = true;

-                            // stack.push(child);

-                            /* start stack.push() */

-                            if (size == data.length)

-                            {

-                                int[] newArr = new int[data.length << 1];

-                                System.arraycopy(data, 0, newArr, 0, data.length);

-                                data = newArr;

-                            }

-                            data[size++] = child;

-                            /* end stack.push() */

+                            data[0] = rootsStack.pop();

+                            size = 1;

+                        }

+                        else

+                            // the work is done

+                        {

+                            break;

                         }

                     }

-                } // end of processing one GC root

+

+                    while (size > 0)

+                    {

+                        /* start stack.pop() */

+                        current = data[--size];

+                        /* end stack.pop */

+

+                        for (int child : outbound.get(current))

+                        {

+                            /*

+                             * No synchronization here. It costs a lot of

+                             * performance It is possible that some bits are marked

+                             * more than once, but this is not a problem

+                             */

+                            if (!bits[child])

+                            {

+                                bits[child] = true;

+                                // stack.push(child);

+                                /* start stack.push() */

+                                if (size == data.length)

+                                {

+                                    int[] newArr = new int[data.length << 1];

+                                    System.arraycopy(data, 0, newArr, 0, data.length);

+                                    data = newArr;

+                                }

+                                data[size++] = child;

+                                /* end stack.push() */

+                            }

+                        }

+                    } // end of processing one GC root

+                }

+                completed = true;

+            } 

+            catch (RuntimeException e)

+            {

+                progressListener.sendUserMessage(Severity.ERROR, Messages.ObjectMarker_ErrorMarkingObjects, e);

+                failure = e;

+            }

+            catch (Error e)

+            {

+                progressListener.sendUserMessage(Severity.ERROR, Messages.ObjectMarker_ErrorMarkingObjects, e);

+                failure = e;

             }

         }

     }

@@ -515,6 +553,8 @@
         static final int MAXSTACK = 100 * 1024;

         /** How many times to loop before checking the global stack */

         private static final int CHECKCOUNT = 10;

+        /** How many times to loop on outbounds before checking the global stack */

+        private static final int CHECKCOUNT2 = 200;

         int localRange;

         final int localRangeLimit;

         SoftReference<int[]> sr;

@@ -599,8 +639,6 @@
                         fillStack();

 

                         // Process the local stack and queue

-                        int current;

-

                         while (size > 0)

                         {

                             /* start stack.pop() */

@@ -611,35 +649,7 @@
                             if (check || checkCount++ >= CHECKCOUNT)

                             {

                                 checkCount = 0;

-                                check = true;

-                                if (queue.size() > 0 && queue.size() + size > RESERVED)

-                                {

-                                    int fromQueue;

-                                    synchronized (rootsStack)

-                                    {

-                                        do

-                                        {

-                                            fromQueue = queue.get();

-                                            check = rootsStack.pushIfWaiting(fromQueue);

-                                        }

-                                        while (check && queue.size() > 0 && queue.size() + size > RESERVED);

-                                    }

-                                    if (!check)

-                                        queue.put(fromQueue);

-                                }

-                                else if (size > RESERVED)

-                                {

-                                    synchronized (rootsStack)

-                                    {

-                                        do

-                                        {

-                                            check = rootsStack.pushIfWaiting(current);

-                                            if (check)

-                                                current = data[--size];

-                                        }

-                                        while (check && size > RESERVED);

-                                    }

-                                }

+                                check = fillRootsStack();

                             }

 

                             // Examine each outbound reference

@@ -654,6 +664,17 @@
                                 if (!bits[child])

                                 {

                                     bits[child] = true;

+                                    // See if we have enough work and other threads need more work. 

+                                    if (queue.size() + size > RESERVED && (check || checkCount++ >= CHECKCOUNT2))

+                                    {

+                                        checkCount = 0;

+                                        synchronized(rootsStack)

+                                        {

+                                            check = rootsStack.pushIfWaiting(child);

+                                        }

+                                        if (check)

+                                            continue;

+                                    }

                                     if (size == 0)

                                     {

                                         // We have emptied the stack, so reset

@@ -693,12 +714,110 @@
                         } // end of processing one GC root

                     }

                 }

+                completed = true;

+            }

+            catch (RuntimeException e)

+            {

+                progressListener.sendUserMessage(Severity.ERROR, Messages.ObjectMarker_ErrorMarkingObjects, e);

+                failure = e;

+            }

+            catch (OutOfMemoryError e)

+            {

+                failure = e;

+                if (emptyLocalStacks())

+                {

+                    progressListener.sendUserMessage(Severity.WARNING, Messages.ObjectMarker_WarningMarkingObjects, e);

+                    // Mark as done as the remaining threads can continue to handle the remaining work

+                    completed = true;

+                }

+                else

+                {

+                    progressListener.sendUserMessage(Severity.ERROR, Messages.ObjectMarker_ErrorMarkingObjects, e);

+                }

+            }

+            catch (Error e)

+            {

+                progressListener.sendUserMessage(Severity.ERROR, Messages.ObjectMarker_ErrorMarkingObjects, e);

+                failure = e;

             }

             finally

             {

                 rootsStack.unlinkThread();

             }

         }

+

+        /**

+         * Fill the root stack with some of the local items

+         * if other threads are waiting and there are still

+         * enough items on the local stack/queue.

+         * @return

+         */

+        private boolean fillRootsStack()

+        {

+            boolean check;

+            check = true;

+            if (queue.size() > 0 && queue.size() + size > RESERVED)

+            {

+                int fromQueue;

+                synchronized (rootsStack)

+                {

+                    do

+                    {

+                        fromQueue = queue.get();

+                        check = rootsStack.pushIfWaiting(fromQueue);

+                    }

+                    while (check && queue.size() > 0 && queue.size() + size > RESERVED);

+                }

+                if (!check)

+                    queue.put(fromQueue);

+            }

+            else if (size > RESERVED)

+            {

+                synchronized (rootsStack)

+                {

+                    do

+                    {

+                        check = rootsStack.pushIfWaiting(current);

+                        if (check)

+                            current = data[--size];

+                    }

+                    while (check && size > RESERVED);

+                }

+            }

+            return check;

+        }

+

+        /**

+         * Empty the local stacks to the global stack.

+         * @return If this was successful.

+         */

+        boolean emptyLocalStacks()

+        {

+            synchronized (rootsStack)

+            {

+                if (DEBUG) System.out.println("emptyLocalStacks "+rootsStack.totalThreads+" "+current+" "+size+" "+queue.size()); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$

+                // Only can requeue if another thread is still running

+                if (rootsStack.totalThreads >= 2)

+                {

+                    if (current != -1)

+                    {

+                        rootsStack.push(current);

+                        current = -1;

+                    }

+                    while (size > 0)

+                    {

+                        rootsStack.push(data[--size]);

+                    }

+                    while (queue.size() > 0)

+                    {

+                        rootsStack.push(queue.get());

+                    }

+                }

+            }

+            if (DEBUG) System.out.println("emptyLocalStacks "+current+" "+size+" "+queue.size()); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$

+            return current == -1 && size == 0 && queue.size() == 0;

+        }

+

         /**

          * Is the objectId in range for the local stack?

          * @param val

diff --git a/plugins/org.eclipse.mat.report/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.report/META-INF/MANIFEST.MF
index 286f8a5..68efda9 100644
--- a/plugins/org.eclipse.mat.report/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.report/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name

 Bundle-Vendor: %Bundle-Vendor

 Bundle-SymbolicName: org.eclipse.mat.report;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-RequiredExecutionEnvironment: J2SE-1.5

 Export-Package: org.eclipse.mat,

  org.eclipse.mat.collect,

diff --git a/plugins/org.eclipse.mat.report/pom.xml b/plugins/org.eclipse.mat.report/pom.xml
index a3ab1c6..5c632f4 100644
--- a/plugins/org.eclipse.mat.report/pom.xml
+++ b/plugins/org.eclipse.mat.report/pom.xml
Binary files differ
diff --git a/plugins/org.eclipse.mat.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.tests/META-INF/MANIFEST.MF
index 45dc803..c465eab 100644
--- a/plugins/org.eclipse.mat.tests/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.tests/META-INF/MANIFEST.MF
@@ -2,13 +2,13 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: Memory Analyzer Tests

 Bundle-SymbolicName: org.eclipse.mat.tests;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-RequiredExecutionEnvironment: J2SE-1.5

 Require-Bundle: org.eclipse.mat.api;bundle-version="1.0.0",

- org.eclipse.mat.parser;bundle-version="1.8.1",

+ org.eclipse.mat.parser;bundle-version="1.9.1",

  org.eclipse.core.runtime,

  org.apache.ant;bundle-version="1.7.0",

- org.eclipse.mat.ui;bundle-version="1.8.1",

+ org.eclipse.mat.ui;bundle-version="1.9.1",

  org.hamcrest.core,

  org.hamcrest.library 

 Bundle-ActivationPolicy: lazy

diff --git a/plugins/org.eclipse.mat.tests/META-INF/tests/performance.xml b/plugins/org.eclipse.mat.tests/META-INF/tests/performance.xml
index 2c3bdeb..57eef08 100644
--- a/plugins/org.eclipse.mat.tests/META-INF/tests/performance.xml
+++ b/plugins/org.eclipse.mat.tests/META-INF/tests/performance.xml
@@ -1,37 +1,37 @@
 <section name="Performance Tests"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 	xmlns="http://www.eclipse.org/mat/report.xsd"

 	xsi:schemaLocation="http://www.eclipse.org/mat/report.xsd ../../../org.eclipse.mat.report/schema/report.xsd">

-	<query name="Paths from GC Roots">		

+	<query name="Paths from GC Roots">

 		<param key="html.separate_file" value="true" />

 		<param key="limit" value="100" />

 		<command>path2gc_reg_test</command>

 	</query>

-	<query name="Merged Paths from GC Roots">		

+	<query name="Merged Paths from GC Roots">

 		<param key="html.separate_file" value="true" />

 		<param key="limit" value="1000" />

 		<command>merged_paths_reg_test</command>

-	</query>				

-	<query name="Retained Size Approx for Histogram">		

+	</query>

+	<query name="Retained Size Approx for Histogram">

 		<param key="html.separate_file" value="true" />

 		<param key="limit" value="50000" />

 		<command>retained_size_histogram_test -approx</command>

 	</query>

-	<query name="Retained Size Approx for Classloaders">		

+	<query name="Retained Size Approx for Classloaders">

 		<param key="html.separate_file" value="true" />

-		<param key="limit" value="50000" />	

-		<command>retained_size_histogram_test -byClassLoader -approx</command>	

+		<param key="limit" value="50000" />

+		<command>retained_size_histogram_test -byClassLoader -approx</command>

 	</query>

-	<query name="Retained Size for Histogram(precise)">		

+	<query name="Retained Size for Histogram(precise)">

 		<param key="html.separate_file" value="true" />

 		<param key="limit" value="50000" />

 		<command>retained_size_histogram_test</command>

 	</query>

-	<query name="Retained Size for Classloaders(precise)">		

+	<query name="Retained Size for Classloaders(precise)">

 		<param key="html.separate_file" value="true" />

-		<param key="limit" value="50000" />	

-		<command>retained_size_histogram_test -byClassLoader </command>	

+		<param key="limit" value="50000" />

+		<command>retained_size_histogram_test -byClassLoader</command>

 	</query>

-	<query name="Immediate Dominators of java.util.HashMap$Entry">		

+	<query name="Immediate Dominators of java.util.HashMap$Entry">

 		<param key="html.separate_file" value="true" />

 		<param key="limit" value="1000" />

 		<command>immediate_dominators java.util.HashMap$Entry</command>

diff --git a/plugins/org.eclipse.mat.tests/META-INF/tests/regression.xml b/plugins/org.eclipse.mat.tests/META-INF/tests/regression.xml
index 3a4ba1e..4e2972b 100644
--- a/plugins/org.eclipse.mat.tests/META-INF/tests/regression.xml
+++ b/plugins/org.eclipse.mat.tests/META-INF/tests/regression.xml
@@ -4,18 +4,18 @@
 	<query name="info">

 		<param key="format" value="csv" />

 		<param key="filename" value="info.csv" />

-		<param key="html.separate_file" value="true" />	

+		<param key="html.separate_file" value="true" />

 		<param key="html.show_table_header" value="false" />

 		<command>heap_dump_overview</command>

-	</query>	

+	</query>

 	<query name="System Properties">

 		<param key="format" value="csv" />

 		<param key="filename" value="System_Properties.csv" />

-		<param key="html.separate_file" value="true" />		

+		<param key="html.separate_file" value="true" />

 		<param key="sort_column" value="Key=ASC" />

-		<param key="limit" value="1000" />		

+		<param key="limit" value="1000" />

 		<command>system_properties</command>

-	</query>	

+	</query>

 	<query name="Class Histogram">

 	    <param key="format" value="csv" />

 		<param key="filename" value="Class_Histogram.csv" />

@@ -39,20 +39,20 @@
 		<param key="filename" value="Dominator_Tree.csv" />

 		<param key="html.separate_file" value="true" />

 		<param key="sort_column" value="#2=DESC,#1=DESC,#0" />

-		<param key="limit" value="50000" />	

+		<param key="limit" value="50000" />

 		<command>dominator_tree</command>

 	</query>

-	<query name="Dominator Tree (binary)">			

-		<command>dom_tree_binary_test</command>				

+	<query name="Dominator Tree (binary)">

+		<command>dom_tree_binary_test</command>

 	</query>

 	<query name="List 1000 Strings">

 		<param key="format" value="csv" />

 		<param key="filename" value="List_1000_Strings.csv" />

 		<param key="html.separate_file" value="true" />

 		<param key="sort_column" value="ADDRESS" />

-		<param key="limit" value="1000" />	

+		<param key="limit" value="1000" />

 		<command>oql "select s.@objectAddress as ADDRESS, toString(s)as VALUE from java.lang.String s"</command>

-	</query>	

+	</query>

 	<query name="Paths from GC Roots">

 		<param key="format" value="csv" />

 		<param key="filename" value="Paths_from_GC_Root.csv" />

@@ -68,15 +68,15 @@
 		<param key="html.separate_file" value="true" />

 		<param key="limit" value="1000" />

 		<command>merged_paths_reg_test</command>

-	</query>	

+	</query>

 	<query name="Immediate Dominators of java.util.HashMap$Entry">

 		<param key="filename" value="Immediate_Dominators_of_java.util.HashMap$Entry.csv" />

 		<param key="format" value="csv" />

-		<param key="html.separate_file" value="true" />		

+		<param key="html.separate_file" value="true" />

 		<param key="sort_column" value="#4=DESC,#3=DESC,#2=DESC,#1=DESC,#0" />

 		<param key="limit" value="1000" />

 		<command>immediate_dominators java.util.HashMap$Entry</command>

-	</query>		

+	</query>

 	<query name="Thread Overview">

 		<param key="filename" value="Thread_Overview.csv" />

 		<param key="format" value="csv" />

@@ -84,5 +84,5 @@
 		<param key="sort_column" value="Name,Object / Stack Frame" />

 		<param key="limit" value="1000" />

 		<command>thread_overview</command>

-	</query>		

+	</query>

 </section>

diff --git a/plugins/org.eclipse.mat.tests/pom.xml b/plugins/org.eclipse.mat.tests/pom.xml
index c93e3e0..3441706 100644
--- a/plugins/org.eclipse.mat.tests/pom.xml
+++ b/plugins/org.eclipse.mat.tests/pom.xml
@@ -8,7 +8,7 @@
 		<groupId>org.eclipse.mat</groupId>

 		<artifactId>parent</artifactId>

 		<relativePath>../../parent</relativePath>

-		<version>1.8.1-SNAPSHOT</version>

+		<version>1.9.1-SNAPSHOT</version>

 	</parent>

 

 	<artifactId>org.eclipse.mat.tests</artifactId>

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java
index de51500..885bcde 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreateCollectionDump.java
@@ -11,17 +11,18 @@
  *******************************************************************************/

 package org.eclipse.mat.tests;

 

-import java.lang.reflect.Array;

 import java.lang.reflect.Constructor;

 import java.lang.reflect.InvocationTargetException;

 import java.lang.reflect.Method;

 import java.lang.reflect.Modifier;

+import java.time.Month;

 import java.util.ArrayDeque;

 import java.util.ArrayList;

 import java.util.Arrays;

 import java.util.Collection;

 import java.util.Collections;

 import java.util.Deque;

+import java.util.Enumeration;

 import java.util.HashMap;

 import java.util.HashSet;

 import java.util.List;

@@ -34,8 +35,14 @@
 import java.util.SortedSet;

 import java.util.TreeMap;

 import java.util.TreeSet;

+import java.util.concurrent.Delayed;

+import java.util.concurrent.TimeUnit;

 import java.util.jar.Attributes;

 

+import javax.management.openmbean.CompositeType;

+import javax.management.openmbean.OpenDataException;

+import javax.management.openmbean.SimpleType;

+import javax.management.openmbean.TabularType;

 import javax.print.attribute.standard.JobStateReason;

 import javax.print.attribute.standard.PrinterStateReason;

 import javax.print.attribute.standard.Severity;

@@ -68,12 +75,14 @@
     {

         // Extend the collections

         List<Collection>l0 = new ArrayList<Collection>();

+        List<Map>l1 = new ArrayList<Map>();

         for (Map m : mapTestData.maps)

         {

             Collection c = m.values();

             if (c.size() == mapTestData.COUNT && c.iterator().next() instanceof String)

             {

                 l0.add(c);

+                //System.out.println("Added " + c.getClass());

             }

         }

         listCollectionTestData2 = new ListCollectionTestData(l0);

@@ -82,36 +91,79 @@
         for (Map m : mapTestData.maps)

         {

             Set s = m.keySet();

+            Set s2 = m.entrySet();

             if (s.size() == mapTestData.COUNT && s.iterator().next() instanceof String)

             {

                 l0.add(s);

-                //l0.add(m.entrySet());

+                //System.out.println("Added " + s.getClass());

+                // Only add the entry set classes so we can detect them at test time

+                if (s2.getClass().getName().contains("EntrySet"))

+                {

+                    l0.add(s2);

+                    //System.out.println("Added " + s2.getClass());

+                }

+                else

+                {

+                    boolean found = false;

+                    for (Collection c : nonListCollectionTestData.collections)

+                    {

+                        if (c.getClass().equals(s2.getClass()))

+                        {

+                            found = true;

+                            break;

+                        }

+                    }

+                    if (!found)

+                        System.out.println("Missing entry set class " + s2.getClass());

+                }

             }

         }

         nonListCollectionTestData2 = new NonListCollectionTestData(l0);

-        

+

         l0.clear();

         for (Map m : emptyMapTestData.maps)

         {

             Collection c = m.values();

-            if (c.size() == mapTestData.COUNT)

+            if (c.size() == 0)

             {

                 l0.add(c);

+                //System.out.println("Added " + c.getClass());

             }

         }

         emptyListCollectionTestData2 = new EmptyListCollectionTestData(l0);

-        

+

         l0.clear();

         for (Map m : emptyMapTestData.maps)

         {

             Set s = m.keySet();

-            if (s.size() == mapTestData.COUNT)

+            Set s2 = m.entrySet();

+            if (s.size() == 0)

             {

                 l0.add(s);

-                //l0.add(m.entrySet());

+                //System.out.println("Added " + s.getClass());

+                if (s2.getClass().getName().contains("EntrySet"))

+                {

+                    l0.add(s2);

+                    //System.out.println("Added " + s.getClass());

+                }

+                else

+                {

+                    boolean found = false;

+                    for (Collection c : emptyNonListCollectionTestData.collections)

+                    {

+                        if (c.getClass().equals(s2.getClass()))

+                        {

+                            found = true;

+                            break;

+                        }

+                    }

+                    if (!found)

+                        System.out.println("Missing entry set class " + s2.getClass());

+                }

             }

         }

         emptyNonListCollectionTestData2 = new EmptyNonListCollectionTestData(l0);

+

     }

 

     public static void main(String[] args) throws Exception

@@ -199,7 +251,9 @@
             List<Collection>cols = new ArrayList<Collection>();

             /*

              * List of classes under test.

-             * Space separate class from static method

+             * Space separated class from static method

+             * 1 entry means use constructor

+             * 2 entries means use static method from class

              */

             String ls[] = new String[] {

                             "java.util.AbstractCollection",

@@ -230,6 +284,9 @@
                             "java.util.Collections emptySet",

                             "java.util.Collections emptySortedSet",

                             "java.util.Collections emptyNavigableSet",

+                            "java.util.Collections list",

+                            "java.util.Collections nCopies",

+                            "java.util.Collections newSetFromMap",

                             "java.util.Collections singleton",

                             "java.util.Collections singletonList",

                             "java.util.Collections synchronizedCollection",

@@ -243,6 +300,8 @@
                             "java.util.Collections unmodifiableSortedSet",

                             "java.util.Collections unmodifiableNavigableSet",

                             "java.util.EnumSet",

+                            "java.util.EnumSet noneOf",

+                            //"java.util.EnumSet allOf",

                             "java.util.HashSet",

                             "javax.print.attribute.standard.JobStateReasons",

                             "java.util.concurrent.LinkedBlockingDeque",

@@ -250,6 +309,7 @@
                             "java.util.LinkedHashSet",

                             "java.util.LinkedList",

                             "java.util.concurrent.LinkedTransferQueue",

+                            "java.util.concurrent.PriorityBlockingQueue",

                             "java.util.PriorityQueue",

                             "javax.management.relation.RoleList",

                             "javax.management.relation.RoleUnresolvedList",

@@ -262,6 +322,7 @@
             values = new String[COUNT];

             for (String cn : ls)

             {

+                // Class for constructor

                 Class<? extends Collection> c = null;

                 // Methods?

                 String cn0 = cn;

@@ -304,42 +365,16 @@
                     }

                 }

 

-                // To use an existing collection constructor

                 fillValues(cn);

-                List<String>arrayVals = new ArrayList<String>();

-                for (int i = 1; i <= COUNT; ++i)

-                {

-                    arrayVals.add(values[i]);

-                }

-                // And a plain 0-based array

-                String values0[] = arrayVals.toArray(new String[arrayVals.size()]);

-                Set<String>setVals = new TreeSet<String>(arrayVals);

-                Set<String>setVals2 = new HashSet<String>(arrayVals);

-                Queue queue = new ArrayDeque(setVals);

-                Object[][] args = new Object[][] { {}, { Integer.valueOf(0) }, { new Integer(COUNT) }, { new Integer(COUNT * 2) },

-                    { arrayVals }, { arrayVals }, { setVals2 }, { setVals2 }, { setVals }, { setVals }, { setVals }, { setVals },

-                    { values0 }, {queue}, {queue},

-                    { arrayVals, String.class}, { arrayVals, String.class}, { setVals, String.class}, { queue, String.class},

-                    { setVals, String.class}, { setVals, String.class},

-                    { values[1] },

-                    { Collections.emptySet() },

-                    { Collections.emptySet() },

-                };

-

-                // Matches argument objects

-                Class[][] cons = new Class[][] { {}, { Integer.TYPE }, { Integer.TYPE }, { Integer.TYPE },

-                                { Collection.class }, { List.class }, { Collection.class }, { Set.class }, { Collection.class }, { Set.class }, { SortedSet.class }, { NavigableSet.class },

-                                { Object[].class }, { Collection.class }, { Deque.class },

-                                { Collection.class, Class.class }, { List.class, Class.class }, { Set.class, Class.class }, { Queue.class, Class.class },

-                                { SortedSet.class, Class.class }, { NavigableSet.class, Class.class },

-                                { Object.class },

-                                { Set.class },

-                                { Collections.class },

-                };

+                // To use an existing collection constructor

+                Class[][] cons = buildArgTypes();

                 int added = 0;

-                // Try the different constuctors / methods

+                // Try the different constructors / methods

                 for (int j = 0; j < cons.length; ++j)

                 {

+                    List<String>arrayVals = new ArrayList<String>();

+                    List<Delayed>delayedVals = new ArrayList<Delayed>();

+                    Object[][] args = buildArgs(arrayVals, delayedVals);

                     Collection cl;

                     try

                     {

@@ -371,24 +406,8 @@
                                 // To use an existing collection constructor

                                 fillValues(cn);

                                 arrayVals = new ArrayList<String>();

-                                for (int i = 1; i <= COUNT; ++i)

-                                {

-                                    arrayVals.add(values[i]);

-                                }

-                                // And a plain 0-based array

-                                values0 = arrayVals.toArray(new String[arrayVals.size()]);

-                                setVals = new TreeSet<String>(arrayVals);

-                                setVals2 = new HashSet<String>(arrayVals);

-                                queue = new ArrayDeque(setVals);

-                                args = new Object[][] { {}, { Integer.valueOf(0) }, { new Integer(COUNT) }, { new Integer(COUNT * 2) },

-                                    { arrayVals }, { arrayVals }, { setVals2 }, { setVals2 }, { setVals }, { setVals }, { setVals }, { setVals },

-                                    { values0 }, {queue}, {queue},

-                                    { arrayVals, String.class}, { arrayVals, String.class}, { setVals, String.class}, { queue, String.class},

-                                    { setVals, String.class}, { setVals, String.class},

-                                    { values[1] },

-                                    { Collections.emptySet() },

-                                    { Collections.emptySet() },

-                                };

+                                delayedVals = new ArrayList<Delayed>();

+                                args = buildArgs(arrayVals, delayedVals);

                                 cl = (Collection)method.invoke(null, args[j]);

                             }

                         }

@@ -404,12 +423,14 @@
                                         cl.add(values[i]);

                                     }

                                 }

-                                // Remove and refill

+                                List vals = new ArrayList(cl.contains(delayedVals.get(0)) ? delayedVals : arrayVals);

+                                 // Remove and refill

                                 int from = 0;

                                 int to = COUNT * 2 / 3;

                                 for (int i = to; i <= COUNT; i += 1)

                                 {

-                                    cl.remove(values[i]);

+                                    //System.out.println(cl.getClass()+" "+arrayVals.size()+" "+delayedVals.size()+" "+delayedVals2.size());

+                                    cl.remove(vals.get(i - 1));

                                 }

                                 if (cl instanceof List)

                                 {

@@ -421,12 +442,12 @@
                                     }

                                     for (i += 3; i < to; i += 3)

                                     {

-                                        l.add(i - 1, values[i]);

+                                        l.add(i - 1, vals.get(i - 1));

                                     }

                                 }

                                 for (int i = to; i <= COUNT; i += 1)

                                 {

-                                    cl.add(values[i]);

+                                    cl.add(vals.get(i - 1));

                                 }

                             }

                             catch (UnsupportedOperationException e)

@@ -460,11 +481,22 @@
                                 }

                             }

                         }

+                        else

+                        {

+                            // Try to make an empty collection

+                            try

+                            {

+                                cl.clear();

+                            }

+                            catch (UnsupportedOperationException e)

+                            {

+                            }

+                        }

                         if (cl.isEmpty() == useEmpty())

                         {

                             cols.add(cl);

                             ++added;

-                            //System.out.println("coll "+cl.size()+" "+cl.getClass()+"  "+useEmpty());

+                            //System.out.println("coll "+cl.size()+" "+cl.getClass()+"  "+useEmpty()+" "+cl);

                         }

                     }

                     catch (NoSuchMethodException e)

@@ -500,6 +532,67 @@
             collections = cols.toArray(new Collection[cols.size()]);

         }

 

+        private Object[][]  buildArgs(List<String> arrayVals, List<Delayed> delayedVals)

+        {

+            for (int i = 1; i <= COUNT; ++i)

+            {

+                arrayVals.add(values[i]);

+                final int fi = i;

+                delayedVals.add(new Delayed() {

+                    public int compareTo(Delayed o)

+                    {

+                        return 0;

+                    }

+                    public long getDelay(TimeUnit unit)

+                    {

+                        return fi;

+                    }

+                });

+            }

+            Map<String,Boolean>mapVals = new TreeMap<String,Boolean>();

+            // And a plain 0-indexed array

+            String values0[] = arrayVals.toArray(new String[arrayVals.size()]);

+            Set<String>setVals = new TreeSet<String>(arrayVals);

+            Set<String>setVals2 = new HashSet<String>(arrayVals);

+            Queue queue = new ArrayDeque(setVals);

+            Enumeration<String> enumer = Collections.enumeration(arrayVals);

+            Object[][] args = new Object[][] { {}, { Integer.valueOf(0) }, { new Integer(COUNT) }, { new Integer(COUNT * 2) },

+                { arrayVals }, { arrayVals }, { setVals2 }, { setVals2 }, { setVals }, { setVals }, { setVals }, { setVals },

+                { values0 }, {queue}, {queue},

+                { arrayVals, String.class}, { arrayVals, String.class}, { setVals, String.class}, { queue, String.class},

+                { setVals, String.class}, { setVals, String.class},

+                { values[1] },

+                { Collections.emptySet() },

+                { Collections.emptySet() },

+                { enumer },

+                { new Integer(COUNT), values[1] },

+                { mapVals },

+                //{ delayedVals },

+                { Month.class },

+            };

+            return args;

+        }

+

+        private Class[][] buildArgTypes()

+        {

+            // Matches argument objects

+            Class[][] cons = new Class[][] { {}, { Integer.TYPE }, { Integer.TYPE }, { Integer.TYPE },

+                            { Collection.class }, { List.class }, { Collection.class }, { Set.class }, { Collection.class }, { Set.class }, { SortedSet.class }, { NavigableSet.class },

+                            { Object[].class }, { Collection.class }, { Deque.class },

+                            { Collection.class, Class.class }, { List.class, Class.class }, { Set.class, Class.class }, { Queue.class, Class.class },

+                            { SortedSet.class, Class.class }, { NavigableSet.class, Class.class },

+                            { Object.class },

+                            { Set.class },

+                            { Collections.class },

+                            { Enumeration.class },

+                            { Integer.TYPE, Object.class },

+                            { Map.class },

+                            //{ Collection.class },

+                            { Class.class },

+            };

+            return cons;

+        }

+

         public void extend(List<Collection>ext)

         {

             List<Collection>l0 = Arrays.asList(collections);

@@ -649,10 +742,19 @@
             }

         }

 

+        public MapTestData(Collection<Map> newmaps)

+        {

+            maps = newmaps.toArray(new Map[newmaps.size()]);

+        }

+

         public MapTestData()

         {

             List<Map>ms = new ArrayList<Map>();

-            // List of maps under test

+            /*

+             * List of maps under test

+             * 1 entry means use constructor

+             * 2 entries means use static method from class

+             */

             String ls[] = new String[] {

                             "java.util.AbstractMap",

                             "java.util.jar.Attributes",

@@ -691,11 +793,14 @@
             keys = new String[COUNT];

             for (String cn : ls)

             {

+                // Class for constructor

                 Class<? extends Map> c = null;

                 String cn0 = cn;

                 // Methods?

                 String ss[] = cn.split(" ", 2);

+                // Method name

                 final String mn;

+                // Class for method name

                 Class<?>cm;

                 if (ss.length > 1)

                 {

@@ -729,31 +834,17 @@
                         continue;

                     }

                 }

-                // To use an existing map constructor

+

                 fillValues(cn);

-                Map<String,String>mapVals = new TreeMap<String,String>();

-                for (int i = 1; i <= COUNT; ++i)

-                {

-                    mapVals.put(keys[i], values[i]);

-                }

-                Map<String,String>mapVals2 = new HashMap<String,String>(mapVals);

-                Object[][] args = new Object[][] { {}, { Integer.valueOf(0) }, { new Integer(COUNT) }, { new Integer(COUNT * 2) },

-                    { mapVals2 } , { mapVals } , { mapVals } , { mapVals },

-                    { mapVals, String.class, String.class }, { mapVals, String.class, String.class }, { mapVals, String.class, String.class },

-                    { keys[1], values[1] },

-                    { Collections.emptyMap() },

-                };

-

-                Class[][] cons = new Class[][] { {}, { Integer.TYPE }, { Integer.TYPE }, { Integer.TYPE },

-                    { Map.class }, { Map.class }, { SortedMap.class }, { NavigableMap.class },

-                    { Map.class, Class.class, Class.class }, { SortedMap.class, Class.class, Class.class }, { NavigableMap.class, Class.class, Class.class },

-                    { Object.class, Object.class },

-                    { Map.class },

-                };

-

+                // Argument types

+                Class[][] cons = buildArgTypes();

                 int added = 0;

                 for (int j = 0; j < cons.length; ++j)

                 {

+                    // To use an existing map constructor

+                    Map<Enum,String>enumVals = new TreeMap<Enum,String>();

+                    Map<String,String>mapVals = new TreeMap<String,String>();

+                    Object[][] args = buildArgs(mapVals, enumVals);

                     Map cl;

                     try

                     {

@@ -771,25 +862,16 @@
                         }

                         else

                         {

-                            cl = (Map)cm.getMethod(mn, cons[j]).invoke(null, args[j]);

+                            Method method = cm.getMethod(mn, cons[j]);

+                            cl = (Map)method.invoke(null, args[j]);

                             c = cl.getClass();

                             if (!c.getName().equals(cn))

                             {

+                                // Class name changed, so rebuild initial values

                                 cn = c.getName();

                                 fillValues(cn);

-                                mapVals = new TreeMap<String,String>();

-                                for (int i = 1; i <= COUNT; ++i)

-                                {

-                                    mapVals.put(keys[i], values[i]);

-                                }

-                                mapVals2 = new HashMap<String,String>(mapVals);

-                                args = new Object[][] { {}, { Integer.valueOf(0) }, { new Integer(COUNT) }, { new Integer(COUNT * 2) },

-                                    { mapVals2 } , { mapVals } , { mapVals } , { mapVals },

-                                    { mapVals, String.class, String.class }, { mapVals, String.class, String.class }, { mapVals, String.class, String.class },

-                                    { keys[1], values[1] },

-                                    { Collections.emptyMap() },

-                                };

-                                cl = (Map)cm.getMethod(mn, cons[j]).invoke(null, args[j]);

+                                args = buildArgs(mapVals, enumVals);

+                                cl = (Map)method.invoke(null, args[j]);

                                 c = cl.getClass();

                             }

                         }

@@ -863,11 +945,22 @@
                                 }

                             }

                         }

+                        else

+                        {

+                            // Try to make an empty map

+                            try

+                            {

+                                cl.clear();

+                            }

+                            catch (UnsupportedOperationException e)

+                            {

+                            }

+                        }

                         if (cl.isEmpty() == useEmpty())

                         {

                             ms.add(cl);

                             ++added;

-                            //System.out.println("map "+cl.size()+" "+cl.getClass()+"  "+useEmpty()+" "+mn+" "+j);

+                            //System.out.println("map "+cl.size()+" "+cl.getClass()+"  "+useEmpty()+" "+mn+" "+j+" "+cl);

                         }

                     }

                     catch (InstantiationException e)

@@ -897,6 +990,57 @@
             maps = ms.toArray(new Map[ms.size()]);

         }

 

+        private Object[][] buildArgs(Map<String, String> mapVals, Map<Enum, String> enumVals)

+        {

+            for (int i = 1; i <= COUNT; ++i)

+            {

+                mapVals.put(keys[i], values[i]);

+                if (i <= 12)

+                    enumVals.put(Month.of(i), values[i]);

+            }

+            SimpleType<String> st[] = Collections.nCopies(COUNT, SimpleType.STRING).toArray(new SimpleType[COUNT]);

+            CompositeType ct1;

+            TabularType tt1;

+            try

+            {

+                // keys[], values[] is 1-offset, we need 0-offset

+                ct1 = new CompositeType("composite test", "a composite type", mapVals.keySet().toArray(new String[COUNT]), mapVals.values().toArray(new String[COUNT]), st);

+                tt1 = new TabularType("tabular test", "testing tabular types with strings", ct1, mapVals.keySet().toArray(new String[COUNT]));

+            }

+            catch (OpenDataException e)

+            {

+                e.printStackTrace();

+                ct1 = null;

+                tt1 = null;

+            }

+            Map<String,String>mapVals2 = new HashMap<String,String>(mapVals);

+            // Arguments

+            Object[][] args = new Object[][] { {}, { Integer.valueOf(0) }, { new Integer(COUNT) }, { new Integer(COUNT * 2) },

+                { mapVals2 } , { mapVals } , { mapVals } , { mapVals },

+                { mapVals, String.class, String.class }, { mapVals, String.class, String.class }, { mapVals, String.class, String.class },

+                { keys[1], values[1] },

+                { Collections.emptyMap() },

+                //{ Month.class },

+                //{ enumVals },

+                //{ tt1 },

+            };

+            return args;

+        }

+

+        private Class[][] buildArgTypes()

+        {

+            Class[][] cons = new Class[][] { {}, { Integer.TYPE }, { Integer.TYPE }, { Integer.TYPE },

+                { Map.class }, { Map.class }, { SortedMap.class }, { NavigableMap.class },

+                { Map.class, Class.class, Class.class }, { SortedMap.class, Class.class, Class.class }, { NavigableMap.class, Class.class, Class.class },

+                { Object.class, Object.class },

+                { Map.class },

+                //{ Class.class },

+                //{ Map.class },

+                //{ TabularType.class },

+            };

+            return cons;

+        }

+

         public String toString()

         {

             return Arrays.toString(maps);

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreatePerformanceDump.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreatePerformanceDump.java
new file mode 100644
index 0000000..77b9d2d
--- /dev/null
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/CreatePerformanceDump.java
@@ -0,0 +1,102 @@
+/*******************************************************************************

+ * Copyright (c) 2019 IBM Corporation.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *    Andrew Johnson (IBM Corporation) - initial API and implementation

+ *******************************************************************************/

+package org.eclipse.mat.tests;

+

+/**

+ * Creates many arrays and initializes them.

+ * Used to stress test object marking, HPROF parsing,

+ * and dominator tree building.

+ *

+ */

+public class CreatePerformanceDump

+{

+    public static final int DEFAULT_M = 200000;

+    public static final int DEFAULT_N = 200;

+    final String a[][];

+    final int numStrings;

+

+    /**

+     * Create lots of arrays of Strings.

+     * @param m size of each sub-array

+     * @param n number of sub-arrays

+     * @param mode How to initialize the arrays.

+     *  0 first sub-array is initalized with different strings, others use same strings

+     *  1 first sub-array is initalized with different strings, others use strings from

+     *    first sub-array or sometimes new copies of the string

+     *  2 first sub-array is initalized with different strings, others use strings from

+     *    the previous sub-array or sometimes new copies of the string

+     *  3 first sub-array is initalized with different strings, others use strings from

+     *    previous sub-arrays or sometimes new copies of the string

+     *  4 sub-arrays filled with just one string

+     *  

+     *  Mode 0 creates m strings

+     *  Modes 1,2,3 create m + m*(n-1)/n strings = m*(2-1/n) strings

+     *  Mode 4 creates a single string

+     */

+    public CreatePerformanceDump(int m, int n, int mode) {

+        a = new String[n][m];

+        int s = 0;

+        for (int i = 0; i < m; ++i)

+        {

+            if (mode == 4 && i > 0)

+            {

+                a[0][i] = a[0][i - 1];

+            }

+            else

+            {

+                a[0][i] = "S"+i;

+                ++s;

+            }

+        }

+        for (int j = 1; j < n; ++j)

+        {

+            for (int i = 0; i < m; ++i)

+            {

+                // fill in the array entries

+                int prev = 0;

+                if (mode == 2)

+                    prev = j - 1;

+                else if (mode == 3)

+                    prev = (int)((long)i * j / m);

+                

+                if (i % n == j && mode > 0 && mode != 4)

+                {

+                    // sometimes with brand new Strings

+                    a[j][i] = new String(a[prev][i]);

+                    ++s;

+                }

+                else

+                {

+                    a[j][i] = a[prev][i];

+                }

+            }

+        }

+        numStrings = s;

+   }

+

+    public static void main(String[] args) throws Exception

+    {

+        int m = args.length > 0 ? Integer.parseInt( args[0]) : DEFAULT_M;

+        int n = args.length > 1 ? Integer.parseInt(args[1]) : DEFAULT_N;

+        int mode = args.length > 2 ? Integer.parseInt(args[2]) : 0;

+        CreatePerformanceDump b = new CreatePerformanceDump(m, n, mode);

+        System.out.println("Acquire Heap Dump NOW (then press any key to terminate program)");

+        int c = System.in.read();

+        // Control-break causes read to return early, so try again for another key to wait

+        // for the dump to complete

+        if (c == -1)

+            c = System.in.read();

+

+        System.out.println("Created array of size " + n + " with each entry holding an array of size " + m

+                        + " of String with " + b.numStrings + " different strings using mode: " + mode

+                        + ". Last entry: " + b.a[b.a.length - 1][b.a[b.a.length - 1].length - 1]);

+        }

+}

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesBase.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesBase.java
index f18f801..9c5376d 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesBase.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesBase.java
@@ -13,6 +13,7 @@
 

 import static org.hamcrest.CoreMatchers.equalTo;

 import static org.hamcrest.Matchers.isOneOf;

+import static org.hamcrest.core.AnyOf.anyOf;

 import static org.hamcrest.core.IsInstanceOf.instanceOf;

 import static org.hamcrest.core.StringContains.containsString;

 import static org.hamcrest.core.StringStartsWith.startsWith;

@@ -21,6 +22,7 @@
 import static org.hamcrest.number.OrderingComparison.lessThanOrEqualTo;

 

 import java.io.Serializable;

+import java.util.regex.Pattern;

 

 import org.eclipse.mat.SnapshotException;

 import org.eclipse.mat.query.IContextObject;

@@ -33,11 +35,38 @@
 import org.eclipse.mat.snapshot.query.SnapshotQuery;

 import org.eclipse.mat.util.MessageUtil;

 import org.eclipse.mat.util.VoidProgressListener;

+import org.hamcrest.Description;

+import org.hamcrest.Matcher;

+import org.hamcrest.TypeSafeMatcher;

 import org.junit.Rule;

 import org.junit.rules.ErrorCollector;

 

 public class ExtractCollectionEntriesBase

 {

+    /**

+     * Hamcrest style matcher for regular expression matching.

+     * Hamcrest 1.1 doesn't have this.

+     * @param regex

+     * @return true if the string matches the pattern

+     */

+    public static Matcher<java.lang.String> matchesPattern(final java.lang.String regex)

+    {

+        return new TypeSafeMatcher<String>() {

+            Pattern pat = Pattern.compile(regex);

+

+            public void describeTo(Description description)

+            {

+                description.appendText("a string matching '" + regex + "'");

+            }

+

+            @Override

+            protected boolean matchesSafely(String item)

+            {

+                return pat.matcher(item).matches();

+            }

+

+        };

+    }

 

     @Rule

     public ErrorCollector collector = new ErrorCollector();

@@ -74,8 +103,8 @@
                         {

                             collector.checkThat(prefix + "List entry should start with the type", cv, startsWith(name));

                         }

-                        collector.checkThat(prefix + "Should end with number or aAbB: " + cv,

-                                    cv.matches(".*([0-9]+|[aAbB]+)$"), equalTo(true));

+                        collector.checkThat(prefix + "Should end with number or aAbB", cv,

+                                    matchesPattern(".*([0-9]+|[aAbB]+)$"));

                     }

                     else

                     {

@@ -130,8 +159,8 @@
                         {

                             collector.checkThat(prefix + "Hash set entry should start with the type", cv, startsWith(name));

                         }

-                        collector.checkThat(prefix + "Should end with number or aAbB: " + cv,

-                                    cv.matches(".*([0-9]+|[aAbB]+)$"), equalTo(true));

+                        collector.checkThat(prefix + "Should end with number or aAbB", cv,

+                                    matchesPattern(".*([0-9]+|[aAbB]+)$"));

                     }

                     else

                     {

@@ -149,19 +178,24 @@
     protected void checkCollection(long objAddress, int numEntries, ISnapshot snapshot) throws SnapshotException

     {

         checkMap(objAddress, numEntries, snapshot);

-        checkHashEntries(objAddress, numEntries, snapshot, false);

+        checkHashEntries(objAddress, numEntries, snapshot, false, false);

     }

 

     /**

      * HashMap entries.

-     * Check keys

+     * Check keys and values.

+     * Map:

+     * 123 : full.class.name:123

+     * Set from map

+     * full.class.name:123 : <other>

      * @param objAddress

      * @param numEntries

      * @param snapshot

      * @param checkValueString

+     * @param isMap whether this is a normal test map, or a map from a set

      * @throws SnapshotException

      */

-    protected void checkHashEntries(long objAddress, int numEntries, ISnapshot snapshot, boolean checkValueString) throws SnapshotException

+    protected void checkHashEntries(long objAddress, int numEntries, ISnapshot snapshot, boolean checkValueString, boolean isMap) throws SnapshotException

     {

         IObject obj = snapshot.getObject(snapshot.mapAddressToId(objAddress));

         String prefix = obj.getTechnicalName()+": ";

@@ -196,24 +230,29 @@
             if (k1 != null)

             {

                 collector.checkThat(prefix+"Key should be an String", k1, instanceOf(String.class));

-                if (checkValueString && k1 instanceof String)

+                if (isMap && checkValueString && k1 instanceof String)

                 {

-                    collector.checkThat(prefix+"Should be a number or aAbB", ((String)k1).matches("[0-9]+|[aAbB]+"), equalTo(true));

+                    collector.checkThat(prefix+"Key should be a number or aAbB", (String)k1, matchesPattern("[0-9]+|[aAbB]+"));

                 }

                 if (checkValueString && k1 instanceof String)

                 {

-                    collector.checkThat(prefix+"Should end with a number or aAbB", ((String)k1).matches(".*([0-9]+|[aAbB]+)$"), equalTo(true));

+                    collector.checkThat(prefix+"Key should end with a number or aAbB", (String)k1, matchesPattern(".*([0-9]+|[aAbB]+)$"));

+                }

+                if (!isMap && checkValueString && k1 instanceof String)

+                {

+                    // Some of the sets are KeySets from Maps so have numeric/aAbB not class names

+                    collector.checkThat(prefix+"Key contains name of collection class or a number or aAbB", (String)k1, anyOf(containsString(obj.getClazz().getName()), matchesPattern("[0-9]+|[aAbB]+")));

                 }

             }

             if (v1 != null)

             {

                 collector.checkThat(prefix+"Value should be an String", v1, instanceOf(String.class));

             }

-            if (checkValueString && k1 instanceof String &&  v1 instanceof String)

+            if (isMap && checkValueString && k1 instanceof String &&  v1 instanceof String)

             {

                 collector.checkThat(prefix+"Value contains key", (String)v1, containsString((String)k1));

             }

-            if (checkValueString && v1 instanceof String)

+            if (isMap && checkValueString && v1 instanceof String)

             {

                 collector.checkThat(prefix+"Value contains name of collection class", (String)v1, containsString(obj.getClazz().getName()));

             }

@@ -282,8 +321,10 @@
         IResultTable table2 = (IResultTable) result2;

         int rowCount2 = table2.getRowCount();

         String className = snapshot.getClassOf(snapshot.mapAddressToId(objAddress)).getName();

-        if (className.equals("java.util.TreeMap") || className.equals("java.util.TreeMap$KeySet") || 

-            className.equals("java.util.concurrent.ConcurrentSkipListMap") ||  className.equals("java.util.concurrent.ConcurrentSkipListMap$KeySet") ||

+        if (className.equals("java.util.TreeMap") || className.equals("java.util.TreeMap$KeySet") ||

+            className.equals("java.util.TreeMap$EntrySet") ||

+            className.equals("java.util.concurrent.ConcurrentSkipListMap") || className.equals("java.util.concurrent.ConcurrentSkipListMap$KeySet") ||

+            className.equals("java.util.concurrent.ConcurrentSkipListMap$EntrySet") ||

             className.equals("java.util.TreeSet") || className.equals("java.util.concurrent.ConcurrentSkipListSet"))

         {

             // TreeMaps and ConcurrentSkipListMap don't appear in the fill ratio report as they

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest2.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest2.java
index dd2c363..4135857 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest2.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/collect/ExtractCollectionEntriesTest2.java
@@ -158,6 +158,7 @@
                         checkCollectionSize(objAddress, numEntries, snapshot);

                         if (!name.startsWith("java.util.concurrent.LinkedBlocking") &&

                                         !name.startsWith("java.util.concurrent.LinkedTransfer") &&

+                                        !name.startsWith("java.util.concurrent.SynchronousQueue") &&

                                         !name.startsWith("java.util.concurrent.ConcurrentLinked"))

                         {

                             checkCollectionFillRatio(objAddress, numEntries, snapshot);

@@ -165,9 +166,12 @@
                         if (!name.contains("Array") && !name.contains("Queue") && !name.contains("Deque")

                             && !(name.startsWith("java.util.Collections") && (name.endsWith("Collection") || name.endsWith("SingletonSet"))))

                         {

-                            checkHashEntries(objAddress, numEntries, snapshot, false);

+                            checkHashEntries(objAddress, numEntries, snapshot, true, false);

                             checkMapCollisionRatio(objAddress, numEntries, snapshot);

-                            checkHashSetObjects(objAddress, numEntries, checkVals, snapshot);

+                            if (!name.contains("EntrySet"))

+                            {

+                                checkHashSetObjects(objAddress, numEntries, checkVals, snapshot);

+                            }

                         }

                         else

                         {

@@ -239,14 +243,27 @@
                     long objAddress = nr.getObjectAddress();

                     int numEntries = 0;

                     checkCollectionSize(objAddress, numEntries, snapshot);

-                    checkHashEntries(objAddress, numEntries, snapshot, true);

+                    checkHashEntries(objAddress, numEntries, snapshot, true, false);

                     String name = nr.getObject().getClazz().getName();

-                    if (!name.contains("Array") && !name.contains("Queue") && !name.contains("Deque"))

+                    if (!name.startsWith("java.util.concurrent.LinkedBlocking") &&

+                                    !name.startsWith("java.util.concurrent.LinkedTransfer") &&

+                                    !name.startsWith("java.util.concurrent.SynchronousQueue") &&

+                                    !name.startsWith("java.util.concurrent.ConcurrentLinked"))

                     {

                         checkCollectionFillRatio(objAddress, numEntries, snapshot);

+                    }

+                    if (!name.contains("Array") && !name.contains("Queue") && !name.contains("Deque")

+                        && !(name.startsWith("java.util.Collections") && (name.endsWith("Collection") || name.endsWith("SingletonSet"))))

+                    {

+                        checkHashEntries(objAddress, numEntries, snapshot, true, false);

                         checkMapCollisionRatio(objAddress, numEntries, snapshot);

                         checkHashSetObjects(objAddress, numEntries, checkVals, snapshot);

                     }

+                    else

+                    {

+                        // Other queries also work with list_entries

+                        checkList(objAddress, numEntries, checkVals, snapshot);

+                    }

                 }

             }

         }

@@ -301,7 +318,7 @@
                     }

                     else

                     {

-                        checkHashEntries(objAddress, numEntries, snapshot, true);

+                        checkHashEntries(objAddress, numEntries, snapshot, true, true);

                         checkMap(objAddress, numEntries, snapshot);

                     }

                 }

@@ -331,7 +348,7 @@
                     ++objectsFound;

                     long objAddress = nr.getObjectAddress();

                     int numEntries = 0;

-                    checkHashEntries(objAddress, numEntries, snapshot, true);

+                    checkHashEntries(objAddress, numEntries, snapshot, true, true);

                     checkMap(objAddress, numEntries, snapshot);

                 }

             }

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/Application.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/Application.java
index 25d0dd8..0649ea3 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/Application.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/Application.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008 SAP AG.

+ * Copyright (c) 2008,2019 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -7,6 +7,7 @@
  *

  * Contributors:

  *    SAP AG - initial API and implementation

+ *    Andrew Johnson - memory usage

  *******************************************************************************/

 package org.eclipse.mat.tests.regression;

 

@@ -105,7 +106,7 @@
         if (report == null)

             throw new SnapshotException(MessageUtil.format("Report not found: {0}", args[2]));

 

-        new TestParseApp(snapshotFile, report).run();

+        new TestParseApp(snapshotFile, report, args[2].contains(":performance")).run();

 

         return IApplication.EXIT_OK;

     }

@@ -119,7 +120,14 @@
                         + "  -performance <folder> <jvmargs> : run performance tests on snapshots in given folder\n" //

                         + "  -cleanAll <folder> : clean index files and test results\n" //

                         + "  -newBaseline <folder> : overwrite existing base line with the last test results\n" //

-                        + "  -parse <snaphost> <report> : parse heap dump and print times\n");

+                        + "  -parse <snaphost> <report> : parse heap dump and print times\n\n"

+                        + "  If <jvmargs> contains two -Xmx values then a binary search is used to find the\n"

+                        + "  minimum value of -Xmx in the range which works.\n"

+                        + "  If <jvmargs> contains two -XX:activeProcessorCount=\n"

+                        + "  or two -Djava.util.concurrent.ForkJoinPool.common.parallelism= values then\n"

+                        + "  the tests are repeated with the range of values from one to the other.\n"

+                        + "  Use double-quotes around <jvmargs> having spaces or multiple options.\n"

+                        );

     }

 

     public void stop()

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/PerfData.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/PerfData.java
index f796ec2..4658fb6 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/PerfData.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/PerfData.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008 SAP AG.

+ * Copyright (c) 2008,2019 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -7,6 +7,7 @@
  *

  * Contributors:

  *    SAP AG - initial API and implementation

+ *    Andrew Johnson - Xmx and thread numbers

  *******************************************************************************/

 

 package org.eclipse.mat.tests.regression;

@@ -15,11 +16,19 @@
 {

     private String testName;

     private String time;

+    private String usedMem;

+    private String freeMem;

+    private String totalMem;

+    private String maxMem;

 

-    public PerfData(String testName, String time)

+    public PerfData(String testName, String time, String usedMem, String freeMem, String totalMem, String maxMem)

     {

         this.testName = testName;

         this.time = time;

+        this.usedMem = usedMem;

+        this.freeMem = freeMem;

+        this.totalMem = totalMem;

+        this.maxMem = maxMem;

     }

 

     public String getTestName()

@@ -31,4 +40,25 @@
     {

         return time;

     }

+

+    public String getUsedMem()

+    {

+        return usedMem;

+    }

+

+    public String getFreeMem()

+    {

+        return freeMem;

+    }

+

+    public String getTotalMem()

+    {

+        return totalMem;

+    }

+

+    public String getMaxMem()

+    {

+        return maxMem;

+    }

+

 }

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/RegTestUtils.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/RegTestUtils.java
index 0473cf1..e66bafc 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/RegTestUtils.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/RegTestUtils.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008 SAP AG.

+ * Copyright (c) 2008, 2019 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -7,6 +7,7 @@
  *

  * Contributors:

  *    SAP AG - initial API and implementation

+ *    Andrew Johnson - CSV changes

  *******************************************************************************/

 package org.eclipse.mat.tests.regression;

 

@@ -16,12 +17,14 @@
 import java.util.List;

 import java.util.regex.Pattern;

 

+import com.ibm.icu.text.DecimalFormatSymbols;

+

 public class RegTestUtils

 {

     static final String BASELINE_EXTENSION = "_baseline";

     static final String TEST_EXTENSION = "_test";

     static final String RESULT_FILENAME = "result.xml";

-    public static final String SEPARATOR = ";";

+    public static final String SEPARATOR = new DecimalFormatSymbols().getDecimalSeparator() == ',' ? ";" : ",";

 

     private static FileFilter filter = new FileFilter()

     {

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestApplication.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestApplication.java
index 34737b4..34d2bfd 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestApplication.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestApplication.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008 SAP AG.

+ * Copyright (c) 2008, 2019 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -7,6 +7,7 @@
  *

  * Contributors:

  *    SAP AG - initial API and implementation

+ *    Andrew Johnson (IBM Corporation) - Xmx and thread numbers

  *******************************************************************************/

 package org.eclipse.mat.tests.regression;

 

@@ -28,6 +29,7 @@
 import java.util.Date;

 import java.util.HashMap;

 import java.util.List;

+import java.util.Locale;

 import java.util.Map;

 import java.util.Properties;

 import java.util.regex.Matcher;

@@ -129,51 +131,150 @@
             throw new IOException(MessageUtil.format("{0} contains no heap dumps", dumpDir.getAbsolutePath()));

 

         List<TestSuiteResult> testResults = new ArrayList<TestSuiteResult>(dumpList.size());

-        for (File dump : dumpList)

+        fileloop: for (File dump : dumpList)

         {

-            TestSuiteResult result = new TestSuiteResult(dump);

-            testResults.add(result);

-

-            try

+            // Multiple -Djava.util.concurrent.ForkJoinPool.common.parallelism= means

+            // run with every value

+            // Also allow -XX:ActiveProcessorCount=

+            String propname1 = "java.util.concurrent.ForkJoinPool.common.parallelism";

+            String prop1 = "-D" + propname1 + "=";

+            String propPattern1 = Pattern.quote(prop1);

+            String propname2 = "XX:ActiveProcessorCount";

+            String prop2 = "-" + propname2 + "=";

+            String propPattern2 = Pattern.quote(prop2);

+            String propPattern = propPattern1 + "|" + propPattern2;

+            // Two instances of property, match first and last, consume space before mid

+            Pattern threadPattern = Pattern.compile("(.*?)("+propPattern+")(\\d+) ?" + 

+                                                     "(.*)\\2(\\d+)" + "(.*)");

+            int minThreads = 1;

+            int maxThreads = 1;

+            Matcher threadMatch = threadPattern.matcher(jvmFlags);

+            if (threadMatch.matches())

             {

-                // prepare test environment

-                cleanIndexFiles(dump, result, true);

+                minThreads = Integer.parseInt(threadMatch.group(3));

+                maxThreads = Integer.parseInt(threadMatch.group(5));

             }

-            catch (Exception e)

+            for (int th = minThreads; th <= maxThreads; ++th)

             {

-                // skip test suite for this heap dump

-                continue;

-            }

-

-            try

-            {

-                // parse the heap dump and execute the test suite

-                parse(dump, jvmFlags, result, !compare);

-            }

-            catch (Exception e)

-            {

-                System.err.println("ERROR: " + e.getMessage());

-                result.addErrorMessage(e.getMessage());

-                continue;

-            }

-

-            // process the result (compare to the baseline)

-            if (compare)

-                processResults(dump, result);

-

-            // do the cleanup only if all the tests succeeded

-            boolean succeed = true;

-            for (SingleTestResult entry : result.getTestData())

-            {

-                if (entry.getResult().equals("Failed"))

+                String jvmFlags1 = this.jvmFlags;

+                if (threadMatch.matches())

                 {

-                    succeed = false;

-                    break;

+                    String prefix = threadMatch.group(1);

+                    String propmatch = threadMatch.group(2);

+                    String mid = threadMatch.group(4);

+                    String suffix = threadMatch.group(6);

+                    jvmFlags1 = prefix + mid + propmatch + th + suffix;

                 }

-            }

-            if (succeed && result.getErrorMessages().isEmpty())

-                cleanIndexFiles(dump, result, false);

 

+                // Multiple -Xmx settings means for us to find the smallest which works

+                String memArg="-Xmx";

+                String memArgPattern = Pattern.quote(memArg);

+                String unitPattern="[kKmMgG]?";

+                // Two instances of Xmx, choose first and last, consume space before mid

+                Pattern mXpattern = Pattern.compile("(.*?)(" + memArgPattern + ")(\\d+)(" + unitPattern + ") ?" +

+                                                     "(.*)\\2(\\d+)(" + unitPattern + ")" +

+                                                     "(.*)");

+                long min = 1;

+                long max = 1;

+                String prefix="",mxmatch="",mid="",unit="",suffix="";

+                Matcher m = mXpattern.matcher(jvmFlags1);

+                if (m.matches())

+                {

+                    // Variable heap size e.g. 

+                    // -Xmx64M -Xms1024M

+                    // -Xmx64m -Xmx1G

+                    prefix = m.group(1);

+                    mxmatch = m.group(2);

+                    min = Long.parseLong(m.group(3));

+                    String unitMin = m.group(4);

+                    mid = m.group(5);

+                    max = Long.parseLong(m.group(6));

+                    String unitMax = m.group(7);

+                    suffix = m.group(8);

+                    // Normalize units

+                    unit = unitMin;

+                    if (!unitMin.equals(unitMax))

+                    {

+                        unit = normalizedUnit(unitMin, unitMax);

+                        min = normalizeToUnit(min, unitMin, unit);

+                        max = normalizeToUnit(max, unitMax, unit);

+                    }

+                }

+                boolean success = false;

+                /*

+                 * Binary search

+                 */

+                do

+                {

+                    long mx = (min + max) >>> 1;

+                    String jvmFlags = m.matches() ? prefix + mid + mxmatch + mx + unit + suffix : jvmFlags1;

+

+                    TestSuiteResult result = new TestSuiteResult(dump, jvmFlags);

+                    testResults.add(result);

+                    try

+                    {

+                        // prepare test environment

+                        cleanIndexFiles(dump, result, true);

+                    }

+                    catch (Exception e)

+                    {

+                        // skip test suite for this heap dump

+                        continue fileloop;

+                    }

+

+                    try

+                    {

+                        // parse the heap dump and execute the test suite

+                        parse(dump, jvmFlags, result, !compare);

+                        max = mx - 1;

+                        success = true;

+                    }

+                    catch (Exception e)

+                    {

+                        min = mx + 1;

+                        if (min > max)

+                        {

+                            // Last -Xmx

+                            if (success)

+                            {

+                                // Previous success, but expected failure with a too small Xmx

+                                testResults.remove(result);

+                                // but we had a success, so delete the index files

+                                cleanIndexFiles(dump, result, false);

+                            }

+                            else

+                            {

+                                System.err.println("ERROR: " + e.getMessage());

+                                result.addErrorMessage(e.getMessage());

+                            }

+                        }

+                        else

+                        {

+                            // Expected failure with a too small Xmx

+                            testResults.remove(result);

+                        }

+                        continue;

+                    }

+

+                    // process the result (compare to the baseline)

+                    if (compare)

+                        processResults(dump, result);

+

+                    // do the cleanup only if all the tests succeeded

+                    boolean succeed = true;

+                    for (SingleTestResult entry : result.getTestData())

+                    {

+                        if (entry.getResult().equals("Failed"))

+                        {

+                            succeed = false;

+                            break;

+                        }

+                    }

+                    if (succeed && result.getErrorMessages().isEmpty())

+                        cleanIndexFiles(dump, result, false);

+

+                } while (min <= max);

+            }

         }

 

         if (!testResults.isEmpty())

@@ -202,11 +303,77 @@
         }

     }

 

+    /**

+     * Convert a value to the new units.

+     * @param value

+     * @param fromUnit

+     * @param toUnit

+     * @return the new value expressed as toUnit

+     */

+    private long normalizeToUnit(long value, String fromUnit, String toUnit)

+    {

+        String u1 = (toUnit+fromUnit).toUpperCase(Locale.ENGLISH);

+        if (u1.equals("K") || u1.equals("KM") || u1.equals("MG") || u1.equals("GT"))

+        {

+            value *= 1024;

+        }

+        else if (u1.equals("M") || u1.equals("KG") || u1.equals("MT"))

+        {

+            value *= 1024 * 1024;

+        }

+        else if (u1.equals("G") || u1.equals("KT"))

+        {

+            value *= 1024 * 1024 * 1024;

+        }

+        else if (u1.equals("T"))

+        {

+            value *= 1024L * 1024 * 1024 * 1024;

+        }

+        return value;

+    }

+

+    /**

+     * Choose the smaller of the two units.

+     * @param unitMin

+     * @param unitMax

+     * @return the smaller unit

+     */

+    private String normalizedUnit(String unitMin, String unitMax)

+    {

+        String unit;

+        if (unitMin.equals(unitMax))

+            unit = unitMin;

+        else if (unitMin.equals(""))

+            unit = unitMin;

+        else if (unitMax.equals(""))

+            unit = unitMax;

+        else if ("tT".contains(unitMin))

+            unit = unitMax;

+        else if ("tT".contains(unitMax))

+            unit = unitMin;

+        else if ("gG".contains(unitMin))

+            unit = unitMax;

+        else if ("gG".contains(unitMax))

+            unit = unitMin;

+        else if ("mM".contains(unitMin))

+            unit = unitMax;

+        else if ("mM".contains(unitMax))

+            unit = unitMin;

+        else if ("kK".contains(unitMin))

+            unit = unitMax;

+        else if ("kK".contains(unitMax))

+            unit = unitMin;

+        else

+            unit = unitMin;

+        return unit;

+    }

+

     private static final String URI = "http://www.eclipse.org/mat/regtest/";

 

     private interface Parameter

     {

         String NAME = "name";

+        String JVM_FLAGS = "jvmFlags";

         String TEST_SUITE = "testSuite";

         String HEAP_DUMP = "heapDump";

         String ERROR = "error";

@@ -245,6 +412,7 @@
             {

                 atts.clear();

                 atts.addAttribute(URI, Parameter.NAME, Parameter.NAME, "CDATA", testSuiteResult.getDumpName());

+                atts.addAttribute(URI, Parameter.JVM_FLAGS, Parameter.JVM_FLAGS, "CDATA", testSuiteResult.getJVMflags());

                 handler.startElement(URI, Parameter.HEAP_DUMP, Parameter.HEAP_DUMP, atts);

                 atts.clear();

 

@@ -330,6 +498,29 @@
 

     }

 

+    /**

+     * Escape CSV fields according to RFC 4180.

+     * @param data

+     * @param sep separator e.g. comma, semicolon

+     * @return escaped data

+     */

+    private String escapeCSVField(String data, String sep)

+    {

+        boolean hasSeparator = data.indexOf(sep) >= 0;

+        boolean hasQuote = data.indexOf('"') >= 0;

+        boolean hasNewLine = data.indexOf('\n') >= 0 || data.indexOf('\r') >= 0 && data.indexOf('\f') >= 0;

+

+        if (hasSeparator || hasQuote || hasNewLine)

+        {

+            if (hasQuote)

+            {

+                data = data.replace("\"", "\"\""); //$NON-NLS-1$ //$NON-NLS-2$

+            }

+            return "\"" + data + "\""; //$NON-NLS-1$ //$NON-NLS-2$

+        }

+        return data;

+    }

+    

     private void generatePerformanceReport(List<TestSuiteResult> results) throws IOException

     {

         File report = new File(dumpDir, String.format("performanceResults_%1$tY%1$tm%1$td%1$tH%1$tM.csv", new Date()));

@@ -345,7 +536,13 @@
                             .append("Test Name").append(RegTestUtils.SEPARATOR) //

                             .append("Date").append(RegTestUtils.SEPARATOR) //

                             .append("Time").append(RegTestUtils.SEPARATOR) //

-                            .append("Build Version").append("\n");

+                            .append("Build Version").append(RegTestUtils.SEPARATOR) //

+                            .append("JVM flags").append(RegTestUtils.SEPARATOR) //

+                            .append("Used memory").append(RegTestUtils.SEPARATOR) //

+                            .append("Free memory").append(RegTestUtils.SEPARATOR) //

+                            .append("Total memory").append(RegTestUtils.SEPARATOR) //

+                            .append("Maximum memory") //

+                            .append("\n");

 

             Bundle bundle = Platform.getBundle("org.eclipse.mat.api");

             String buildId = (bundle != null) ? bundle.getHeaders().get("Bundle-Version").toString()

@@ -359,11 +556,17 @@
 

                 for (PerfData record : result.getPerfData())

                 {

-                    out.append(relativePath).append(RegTestUtils.SEPARATOR) //

-                                    .append(record.getTestName()).append(RegTestUtils.SEPARATOR) //

-                                    .append(date).append(RegTestUtils.SEPARATOR) //

-                                    .append(record.getTime()).append(RegTestUtils.SEPARATOR) //

-                                    .append(buildId).append("\n");

+                    out.append(escapeCSVField(relativePath, RegTestUtils.SEPARATOR)).append(RegTestUtils.SEPARATOR) //

+                       .append(escapeCSVField(record.getTestName(), RegTestUtils.SEPARATOR)).append(RegTestUtils.SEPARATOR) //

+                       .append(escapeCSVField(date, RegTestUtils.SEPARATOR)).append(RegTestUtils.SEPARATOR) //

+                       .append(escapeCSVField(record.getTime(), RegTestUtils.SEPARATOR)).append(RegTestUtils.SEPARATOR) //

+                       .append(escapeCSVField(buildId, RegTestUtils.SEPARATOR)).append(RegTestUtils.SEPARATOR) //

+                       .append(escapeCSVField(result.getJVMflags(), RegTestUtils.SEPARATOR)).append(RegTestUtils.SEPARATOR) //

+                       .append(escapeCSVField(record.getUsedMem(), RegTestUtils.SEPARATOR)).append(RegTestUtils.SEPARATOR) //

+                       .append(escapeCSVField(record.getFreeMem(), RegTestUtils.SEPARATOR)).append(RegTestUtils.SEPARATOR) //

+                       .append(escapeCSVField(record.getTotalMem(), RegTestUtils.SEPARATOR)).append(RegTestUtils.SEPARATOR) //

+                       .append(escapeCSVField(record.getMaxMem(), RegTestUtils.SEPARATOR)) //

+                       .append("\n");

                 }

             }

 

@@ -573,7 +776,7 @@
         // get result file name

         String resultsFileName = dumpFile.getAbsolutePath().substring(0, dumpFile.getAbsolutePath().lastIndexOf('.'))

                         + "_Regression_Tests.zip";

-        System.out.println("Unzip: unziping test result file " + resultsFileName);

+        System.out.println("Unzip: unzipping test result file " + resultsFileName);

 

         File originFile = new File(resultsFileName);

         File targetFile = new File(baselineDir, originFile.getName());

@@ -586,7 +789,7 @@
         }

         else

         {

-            String message = "ERROR: Failed coping test results file " + resultsFileName

+            String message = "ERROR: Failed copying test results file " + resultsFileName

                             + " to the destination folder " + baselineDir;

             result.addErrorMessage(message);

             System.err.println(message);

@@ -668,12 +871,13 @@
         // extract parsing time

         if (extractTime)

         {

-            Pattern pattern = Pattern.compile("Task: (.*) ([0-9]*) ms");

+            Pattern pattern = Pattern.compile("Task: (.*) ([0-9]+) ms used ([0-9]+) free ([0-9]+) total ([0-9]+) max ([0-9]+)");

             for (String line : outputGobbler.getLines())

             {

                 Matcher matcher = pattern.matcher(line);

                 if (matcher.matches())

-                    result.addPerfData(new PerfData(matcher.group(1), matcher.group(2)));

+                    result.addPerfData(new PerfData(matcher.group(1), matcher.group(2), 

+                        matcher.group(3), matcher.group(4), matcher.group(5), matcher.group(6)));

             }

         }

     }

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestParseApp.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestParseApp.java
index 1f5f20b..19fc2eb 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestParseApp.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestParseApp.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008 SAP AG.

+ * Copyright (c) 2008, 2019 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -7,6 +7,7 @@
  *

  * Contributors:

  *    SAP AG - initial API and implementation

+ *    Andrew Johnson (IBM Corporation) - Xmx and thread numbers

  *******************************************************************************/

 package org.eclipse.mat.tests.regression;

 

@@ -25,16 +26,18 @@
 {

     private File snapshotFile;

     private Spec report;

+    private boolean showMem;

 

-    public TestParseApp(File snapshotFile, Spec report)

+    public TestParseApp(File snapshotFile, Spec report, boolean showMem)

     {

         this.snapshotFile = snapshotFile;

         this.report = report;

+        this.showMem = showMem;

     }

 

     public void run() throws Exception

     {

-        IProgressListener listener = new ClockedProgressListener(snapshotFile, System.out);

+        IProgressListener listener = new ClockedProgressListener(snapshotFile, System.out, showMem);

 

         ISnapshot snapshot = null;

 

@@ -50,9 +53,10 @@
         finally

         {

             if (snapshot != null) SnapshotFactory.dispose(snapshot);

-        }

 

-        listener.done();

+            // If there was an error then this will still show the last message

+            listener.done();

+        }

     }

 

     private static class ClockedProgressListener implements IProgressListener

@@ -62,11 +66,12 @@
         private int count = 0;

         private String absolutePath;

         private String fileName;

+        private boolean showMem;

 

         private long timestamp = 0;

         private String lastMessage = null;

 

-        /* package */ClockedProgressListener(File snapshot, PrintStream out)

+        /* package */ClockedProgressListener(File snapshot, PrintStream out, boolean showMemUsage)

         {

             this.out = out;

             this.timestamp = System.currentTimeMillis();

@@ -77,6 +82,7 @@
             int p = this.fileName.lastIndexOf('.');

             if (p >= 0)

                 this.fileName = this.fileName.substring(0, p);

+            this.showMem = showMemUsage;

         }

 

         public void beginTask(String name, int totalWork)

@@ -99,8 +105,20 @@
                 if (p >= 0)

                     lastMessage = lastMessage.substring(0, p) + "DUMP" + lastMessage.substring(p + fileName.length());

 

-                out.println(String.format("Task: [%02d] %s %s ms", ++count, lastMessage, String

-                                .valueOf(now - timestamp)));

+                if (showMem)

+                {

+                    long freeMem = Runtime.getRuntime().freeMemory();

+                    long totalMem = Runtime.getRuntime().totalMemory();

+                    long maxMem = Runtime.getRuntime().maxMemory();

+                    long usedMem = totalMem - freeMem;

+                    out.println(String.format("Task: [%02d] %s %s ms used %d free %d total %d max %d", ++count, lastMessage, String

+                                    .valueOf(now - timestamp), usedMem, freeMem, totalMem, maxMem));

+                }

+                else

+                {

+                    out.println(String.format("Task: [%02d] %s %s ms", ++count, lastMessage, String

+                                    .valueOf(now - timestamp)));

+                }

             }

 

             this.lastMessage = name;

diff --git a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestSuiteResult.java b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestSuiteResult.java
index fb04a70..c15e7f5 100644
--- a/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestSuiteResult.java
+++ b/plugins/org.eclipse.mat.tests/src/org/eclipse/mat/tests/regression/TestSuiteResult.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008 SAP AG.

+ * Copyright (c) 2008,2019 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -7,6 +7,7 @@
  *

  * Contributors:

  *    SAP AG - initial API and implementation

+ *    Andrew Johnson - Xmx and thread numbers

  *******************************************************************************/

 package org.eclipse.mat.tests.regression;

 

@@ -17,13 +18,15 @@
 /*package*/class TestSuiteResult

 {

     private File snapshot;

+    private String jvmFlags;

     private List<SingleTestResult> singleTestResult = new ArrayList<SingleTestResult>();

     private List<String> errorMessages = new ArrayList<String>();

     private List<PerfData> perfData = new ArrayList<PerfData>();

 

-    public TestSuiteResult(File snapshot)

+    public TestSuiteResult(File snapshot, String jvmFlags)

     {

         this.snapshot = snapshot;

+        this.jvmFlags = jvmFlags;

     }

 

     public String getDumpName()

@@ -36,6 +39,11 @@
         return snapshot;

     }

 

+    public String getJVMflags()

+    {

+        return jvmFlags;

+    }

+

     public List<SingleTestResult> getTestData()

     {

         return singleTestResult;

diff --git a/plugins/org.eclipse.mat.ui.capabilities/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.ui.capabilities/META-INF/MANIFEST.MF
index 53fabbf..cbe85a8 100644
--- a/plugins/org.eclipse.mat.ui.capabilities/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.ui.capabilities/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: org.eclipse.mat.ui.capabilities;singleton:=true
-Bundle-Version: 1.8.1.qualifier
+Bundle-Version: 1.9.1.qualifier
 Bundle-Vendor: %Bundle-Vendor
 Require-Bundle: org.eclipse.ui;bundle-version="3.4.0"
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.mat.ui.help/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.ui.help/META-INF/MANIFEST.MF
index ecdcec2..d0bff95 100644
--- a/plugins/org.eclipse.mat.ui.help/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.ui.help/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: %Bundle-Name

 Bundle-SymbolicName: org.eclipse.mat.ui.help;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-Vendor: %Bundle-Vendor

 Require-Bundle: org.eclipse.core.runtime;bundle-version="3.3.100",

  org.eclipse.help;bundle-version="3.3.0",

diff --git a/plugins/org.eclipse.mat.ui.help/intro/css/memory_analyzer_48.png b/plugins/org.eclipse.mat.ui.help/intro/css/memory_analyzer_48.png
new file mode 100644
index 0000000..39a9263
--- /dev/null
+++ b/plugins/org.eclipse.mat.ui.help/intro/css/memory_analyzer_48.png
Binary files differ
diff --git a/plugins/org.eclipse.mat.ui.help/intro/css/overview.css b/plugins/org.eclipse.mat.ui.help/intro/css/overview.css
index 75381c8..f21fe75 100644
--- a/plugins/org.eclipse.mat.ui.help/intro/css/overview.css
+++ b/plugins/org.eclipse.mat.ui.help/intro/css/overview.css
@@ -1,2 +1,2 @@
-a#mat-overview img { background-image : url(overview.gif); }

-a#mat-overview:hover img { background-image : url(overview.gif); }
\ No newline at end of file
+a#mat-overview img { background-image : url(memory_analyzer_48.png); }

+a#mat-overview:hover img { background-image : url(memory_analyzer_48.png); }
\ No newline at end of file
diff --git a/plugins/org.eclipse.mat.ui.help/intro/css/tutorials.css b/plugins/org.eclipse.mat.ui.help/intro/css/tutorials.css
index 4342d3c..7206b2e 100644
--- a/plugins/org.eclipse.mat.ui.help/intro/css/tutorials.css
+++ b/plugins/org.eclipse.mat.ui.help/intro/css/tutorials.css
@@ -1,2 +1,2 @@
-a#mat-tutorials img { background-image : url(tutorial.gif); }

-a#mat-tutorials:hover img { background-image : url(tutorial.gif); }

+a#mat-tutorials img { background-image : url(memory_analyzer_48.png); }

+a#mat-tutorials:hover img { background-image : url(memory_analyzer_48.png); }

diff --git a/plugins/org.eclipse.mat.ui.help/intro/css/whatsnew.css b/plugins/org.eclipse.mat.ui.help/intro/css/whatsnew.css
index b6dbaa3..5eac95c 100644
--- a/plugins/org.eclipse.mat.ui.help/intro/css/whatsnew.css
+++ b/plugins/org.eclipse.mat.ui.help/intro/css/whatsnew.css
@@ -1,2 +1,2 @@
-a#mat-whatsnew img { background-image : url(memory_analyzer_32.gif); }

-a#mat-whatsnew:hover img { background-image : url(memory_analyzer_32.gif); }
\ No newline at end of file
+a#mat-whatsnew img { background-image : url(memory_analyzer_48.png); }

+a#mat-whatsnew:hover img { background-image : url(memory_analyzer_48.png); }
\ No newline at end of file
diff --git a/plugins/org.eclipse.mat.ui.help/legal.dita b/plugins/org.eclipse.mat.ui.help/legal.dita
index 52dbbb6..eaefaec 100644
--- a/plugins/org.eclipse.mat.ui.help/legal.dita
+++ b/plugins/org.eclipse.mat.ui.help/legal.dita
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>

 <!--

-    Copyright (c) 2008, 2018 SAP AG.

+    Copyright (c) 2008, 2019 SAP AG.

     All rights reserved. This program and the accompanying materials

     are made available under the terms of the Eclipse Public License v1.0

     which accompanies this distribution, and is available at

@@ -16,7 +16,7 @@
 		<copyright>

 			<copyryear year=""></copyryear>

 			<copyrholder>

-				Copyright (c) 2008, 2018 SAP AG and others.

+				Copyright (c) 2008, 2019 SAP AG and others.

 			    All rights reserved. This program and the accompanying materials

 			    are made available under the terms of the Eclipse Public License v1.0

 			    which accompanies this distribution, and is available at

@@ -30,7 +30,7 @@
 		<section>

 			<title>Notices</title>

 			<p>

-				The material in this guide is Copyright (c) SAP AG and IBM Corporation 2008, 2018

+				The material in this guide is Copyright (c) SAP AG and IBM Corporation 2008, 2019

 			</p>

 			<p>

 				<xref format="html" href="about.html">Terms and conditions regarding the use of this guide.</xref> 

diff --git a/plugins/org.eclipse.mat.ui.help/legal.html b/plugins/org.eclipse.mat.ui.help/legal.html
index e2e8be6..bd75be4 100644
--- a/plugins/org.eclipse.mat.ui.help/legal.html
+++ b/plugins/org.eclipse.mat.ui.help/legal.html
@@ -6,8 +6,8 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <meta name="DC.Type" content="reference"/>
 <meta name="DC.Title" content="Legal"/>
-<meta name="copyright" content="Copyright (c) 2008, 2018 SAP AG and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
-<meta name="DC.Rights.Owner" content="Copyright (c) 2008, 2018 SAP AG and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
+<meta name="copyright" content="Copyright (c) 2008, 2019 SAP AG and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
+<meta name="DC.Rights.Owner" content="Copyright (c) 2008, 2019 SAP AG and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
 <meta name="DC.Format" content="XHTML"/>
 <meta name="DC.Identifier" content="ref_noteworthy"/>
 <meta name="DC.Language" content="en-us"/>
@@ -26,7 +26,7 @@
 		<div class="section"><h2 class="title sectiontitle">Notices</h2>
 			
 			<p class="p">
-				The material in this guide is Copyright (c) SAP AG and IBM Corporation 2008, 2018
+				The material in this guide is Copyright (c) SAP AG and IBM Corporation 2008, 2019
 			</p>
 
 			<p class="p">
diff --git a/plugins/org.eclipse.mat.ui.help/noteworthy.dita b/plugins/org.eclipse.mat.ui.help/noteworthy.dita
index 4c20b1d..8dfabf6 100644
--- a/plugins/org.eclipse.mat.ui.help/noteworthy.dita
+++ b/plugins/org.eclipse.mat.ui.help/noteworthy.dita
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>

 <!--

-    Copyright (c) 2008, 2018 SAP AG and others.

+    Copyright (c) 2008, 2019 SAP AG and others.

     All rights reserved. This program and the accompanying materials

     are made available under the terms of the Eclipse Public License v1.0

     which accompanies this distribution, and is available at

@@ -8,19 +8,19 @@
    

     Contributors:

         SAP AG - initial API and implementation

-        IBM Corporation - 1.4, 1.7, 1.8 updates

+        IBM Corporation - 1.4, 1.7, 1.8, 1.9 updates

  -->

 <!DOCTYPE reference PUBLIC "-//OASIS//DTD DITA Reference//EN" "reference.dtd" >

 <reference id="ref_noteworthy" xml:lang="en-us">

 	<title>New and Noteworthy</title>

 	<shortdesc>Here are descriptions of some of the more interesting or

-		significant changes made to the Memory Analyzer for the 1.8 release.

+		significant changes made to the Memory Analyzer for the 1.9 release.

 	</shortdesc>

 	<prolog>

 		<copyright>

 			<copyryear year=""></copyryear>

 			<copyrholder>

-				Copyright (c) 2008, 2018 SAP AG and others.

+				Copyright (c) 2008, 2019 SAP AG and others.

 			    All rights reserved. This program and the accompanying materials

 			    are made available under the terms of the Eclipse Public License v1.0

 			    which accompanies this distribution, and is available at

@@ -31,86 +31,44 @@
 	<refbody>

 		<section>

 			<title>Enhancements and fixes</title>

-			<p>Eclipse Memory Analyzer 1.8 has support for generating and analyzing dumps

-			from Java 9, Java 10 as well as Java 1.8 and previous versions.

-			The acquire dump dialog and collection queries have been enhanced for this.</p>

+			<p>

+			One of the main enhancements is the <xref href="tasks/exportdump.dita">export HPROF</xref> query. This allows a new HPROF file to be generated from a snapshot,

+			with the redaction of data such as character or byte array values or field values. This could be useful

+			to allow future analysis of the new HPROF dump without exposing sensitive data.

+			</p>

+			<p>There is also a way to compare two heap dumps with a basic batch mode report using <xref href="tasks/batch.dita"><cmdname>ParseHeapDump</cmdname></xref>.</p>

+			<p>Memory Analyzer 1.8.1 also added more icons for queries and icons which worked better in high contrast or dark modes.</p>

 			<ul>

-			<li>Memory Analyzer RCP is now built with Photon.

-			The following stand-alone builds are available:

-			<ul>

-			<li>Windows (x86)</li>

-			<li>Windows (x86_64)</li>

-			<li>Mac OSX (Mac/Cocoa/x86_64)</li>

-			<li>Linux (x86/GTK+)</li>

-			<li>Linux (x86_64/GTK+)</li>

-			<li>Linux (PPC64/GTK+)</li>

-			<li>Linux (PPC64le/GTK+)</li>

-			</ul>

-			<note>

-			Because of the <xref format="html" href="https://dev.eclipse.org/mhonarc/lists/eclipse-dev/msg10207.html">removal of Eclipse platform support</xref> for certain operating systems for 

-			<xref format="html" href="https://www.eclipse.org/eclipse/news/4.7/platform.php#unix-platforms-dropped">

-			Oxygen</xref> and later the following stand-alone builds are not available for Memory Analyzer 1.8:

-			<ul importance="obsolete">

-			<li><i>Linux (PPC/GTK+)</i></li>

-			<li><i>Linux (s390/GTK+)</i></li>

-			<li><i>Linux (s390x/GTK+)</i></li>

-			<li><i>Solaris 8 (x86/GTK+)</i></li>

-			<li><i>Solaris 8 (SPARC/GTK+)</i></li>

-			<li><i>HP-UX (IA64/GTK+)</i></li>

-			<li><i>AIX (PPC/GTK+)</i></li>

-			<li><i>AIX (PPC64/GTK+)</i></li>

-			</ul>

-			It is possible that Memory Analyzer 1.8 could be installed into 

-			<xref format="html" href="http://archive.eclipse.org/eclipse/downloads/drops4/R-4.6.3-201703010400/">

-			Eclipse Neon for those platforms</xref> or into 

-			<xref format="html" href="https://www.eclipse.org/mat/previousReleases.php">previous releases of Eclipse Memory Analyzer</xref>

-			but this has not been tested.

-			</note>

-			<note>

-			Because of the <xref format="html" href="https://wiki.eclipse.org/Eclipse/Installation/Java8Required">requirements of Eclipse Neon and later</xref>, Java version 1.8 or later is required to run the RCP.

-			<xref format="html" href="https://www.eclipse.org/mat/previousReleases.php">Previous releases of Eclipse Memory Analyzer</xref>

-			could run with Java 1.6, 1.7 and 1.8.

-			</note>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=317289">317289</xref> Extract information from Exception objects in the heap dumps

 			</li>

-			<li>Memory Analyzer can now work with Java virtual machines, version 9 and version 10,

-			as well as 1.8. Dumps from JVMs versions 1.5, 1.6 and 1.7 are still handled.

-			Memory Analyzer has been tested with JVMs of the

-			following types:

-			<ul>

-			<li>Oracle JVMs</li>

-			<li>OpenJDK JVMs</li>

-			<li>IBM JVMs</li>

-			<li>OpenJ9 JVMs</li>

-			</ul>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=380600">380600</xref> Resave Heap Dump without Unreachable Objects

 			</li>

-			<li>Fixes for new Java 9 string format</li>

-			<li>Acquire heap dumps - various improvements:

-			<ul>

-			<li>Attach API provider now works using <codeph>com.sun.tools.attach</codeph>

-			allowing it to work with Oracle JVMs and IBM JVMs, version 1.8 SR5 and later.

-			Earlier IBM JVMs continue to work using <codeph>com.ibm.tools.attach</codeph></li>

-			<li>Sort columns of PID and provider</li>

-			<li>Resizing of columns with window</li>

-			<li>More help, including links to provider help</li>

-			<li>Processes unavailable for dumps marked in <i>italics</i></li>

-			<li>Attach API provide can generate HPROF dumps for Oracle and OpenJDK JVMS

-			using HotSpot MX bean.</li>

-			<li>Configure Heap Dump providers page jumps to appropriate provider when

-			selected from a process.</li>

-			</ul>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=519274">519274</xref> Redacted Binary or PHD dump so as to protect privacy data

 			</li>

-			<li>Equinox Bundle Explorer now handles more recent Eclipse versions.</li>

-			<li>More collections handled by collection queries, including collections from Java 9 and Java 10.</li>

-			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=520908">520908</xref>: Invalid thread object in ThreadOverviewQuery causes whole query to fail</li>

-			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=521999">521999</xref>: pString values not displayed analyzing some IBM core dumps</li>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=538953">538953</xref> Create an option for DTFJIndexBuilder to suppress native class sizes

+			</li>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=539750">539750</xref> java.util.ConcurrentModificationException with Calculate precise retained size and sort

+			</li>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=541245">541245</xref> Exceptions with result filtering

+			</li>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=541286">541286</xref> Missing shallow heap size values in comparison tables

+			</li>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=541539">541539</xref> Simple batch mode comparison of two snapshots

+			</li>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=543045">543045</xref> Eclipse MAT does not show complete actual heap size(Heap dump size) on overview tab.

+			</li>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=537579">537579</xref> ArrayIndexOutOfBoundsException in HashMapObjectLong.resize

+			</li>

+			<li>Fix for <xref format="html" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=539751">539751</xref> Unhandled event loop exception - InjectionException - WidgetMethodHandler is not handled for for command Command Copy

+			</li> 

 			</ul>

 		</section>

 		

 		<section>

-			<title>New and Noteworthy for Memory Analyzer 1.7</title>

+			<title>New and Noteworthy for Memory Analyzer 1.8</title>

 			<p>

-				The New and Noteworthy document for version 1.7 is available 

-				<xref format="html" href="http://www.eclipse.org/mat/1.7.0/noteworthy.html">here</xref>.

+				The New and Noteworthy document for version 1.8 is available 

+				<xref format="html" href="http://www.eclipse.org/mat/1.8.0/noteworthy.html">here</xref>.

 			</p>

 		</section>

 

diff --git a/plugins/org.eclipse.mat.ui.help/noteworthy.html b/plugins/org.eclipse.mat.ui.help/noteworthy.html
index e35290a..0167e21 100644
--- a/plugins/org.eclipse.mat.ui.help/noteworthy.html
+++ b/plugins/org.eclipse.mat.ui.help/noteworthy.html
@@ -6,10 +6,10 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <meta name="DC.Type" content="reference"/>
 <meta name="DC.Title" content="New and Noteworthy"/>
-<meta name="abstract" content="Here are descriptions of some of the more interesting or significant changes made to the Memory Analyzer for the 1.8 release."/>
-<meta name="description" content="Here are descriptions of some of the more interesting or significant changes made to the Memory Analyzer for the 1.8 release."/>
-<meta name="copyright" content="Copyright (c) 2008, 2018 SAP AG and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
-<meta name="DC.Rights.Owner" content="Copyright (c) 2008, 2018 SAP AG and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
+<meta name="abstract" content="Here are descriptions of some of the more interesting or significant changes made to the Memory Analyzer for the 1.9 release."/>
+<meta name="description" content="Here are descriptions of some of the more interesting or significant changes made to the Memory Analyzer for the 1.9 release."/>
+<meta name="copyright" content="Copyright (c) 2008, 2019 SAP AG and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
+<meta name="DC.Rights.Owner" content="Copyright (c) 2008, 2019 SAP AG and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
 <meta name="DC.Format" content="XHTML"/>
 <meta name="DC.Identifier" content="ref_noteworthy"/>
 <meta name="DC.Language" content="en-us"/>
@@ -24,134 +24,65 @@
 	
 	
 	<div class="body refbody"><p class="shortdesc">Here are descriptions of some of the more interesting or
-		significant changes made to the Memory Analyzer for the 1.8 release.
+		significant changes made to the Memory Analyzer for the 1.9 release.
 	</p>
 
 		<div class="section"><h2 class="title sectiontitle">Enhancements and fixes</h2>
 			
-			<p class="p">Eclipse Memory Analyzer 1.8 has support for generating and analyzing dumps
-			from Java 9, Java 10 as well as Java 1.8 and previous versions.
-			The acquire dump dialog and collection queries have been enhanced for this.</p>
+			<p class="p">
+			One of the main enhancements is the <a class="xref" href="tasks/exportdump.html">export HPROF</a> query. This allows a new HPROF file to be generated from a snapshot,
+			with the redaction of data such as character or byte array values or field values. This could be useful
+			to allow future analysis of the new HPROF dump without exposing sensitive data.
+			</p>
+
+			<p class="p">There is also a way to compare two heap dumps with a basic batch mode report using <a class="xref" href="tasks/batch.html"><span class="keyword cmdname">ParseHeapDump</span></a>.</p>
+
+			<p class="p">Memory Analyzer 1.8.1 also added more icons for queries and icons which worked better in high contrast or dark modes.</p>
 
 			<ul class="ul">
-			<li class="li">Memory Analyzer RCP is now built with Photon.
-			The following stand-alone builds are available:
-			<ul class="ul">
-			<li class="li">Windows (x86)</li>
-
-			<li class="li">Windows (x86_64)</li>
-
-			<li class="li">Mac OSX (Mac/Cocoa/x86_64)</li>
-
-			<li class="li">Linux (x86/GTK+)</li>
-
-			<li class="li">Linux (x86_64/GTK+)</li>
-
-			<li class="li">Linux (PPC64/GTK+)</li>
-
-			<li class="li">Linux (PPC64le/GTK+)</li>
-
-			</ul>
-
-			<div class="note note"><span class="notetitle">Note:</span> 
-			Because of the <a class="xref" href="https://dev.eclipse.org/mhonarc/lists/eclipse-dev/msg10207.html">removal of Eclipse platform support</a> for certain operating systems for 
-			<a class="xref" href="https://www.eclipse.org/eclipse/news/4.7/platform.php#unix-platforms-dropped">
-			Oxygen</a> and later the following stand-alone builds are not available for Memory Analyzer 1.8:
-			<ul class="ul">
-			<li class="li"><em class="ph i">Linux (PPC/GTK+)</em></li>
-
-			<li class="li"><em class="ph i">Linux (s390/GTK+)</em></li>
-
-			<li class="li"><em class="ph i">Linux (s390x/GTK+)</em></li>
-
-			<li class="li"><em class="ph i">Solaris 8 (x86/GTK+)</em></li>
-
-			<li class="li"><em class="ph i">Solaris 8 (SPARC/GTK+)</em></li>
-
-			<li class="li"><em class="ph i">HP-UX (IA64/GTK+)</em></li>
-
-			<li class="li"><em class="ph i">AIX (PPC/GTK+)</em></li>
-
-			<li class="li"><em class="ph i">AIX (PPC64/GTK+)</em></li>
-
-			</ul>
-
-			It is possible that Memory Analyzer 1.8 could be installed into 
-			<a class="xref" href="http://archive.eclipse.org/eclipse/downloads/drops4/R-4.6.3-201703010400/">
-			Eclipse Neon for those platforms</a> or into 
-			<a class="xref" href="https://www.eclipse.org/mat/previousReleases.php">previous releases of Eclipse Memory Analyzer</a>
-			but this has not been tested.
-			</div>
-
-			<div class="note note"><span class="notetitle">Note:</span> 
-			Because of the <a class="xref" href="https://wiki.eclipse.org/Eclipse/Installation/Java8Required">requirements of Eclipse Neon and later</a>, Java version 1.8 or later is required to run the RCP.
-			<a class="xref" href="https://www.eclipse.org/mat/previousReleases.php">Previous releases of Eclipse Memory Analyzer</a>
-			could run with Java 1.6, 1.7 and 1.8.
-			</div>
-
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=317289">317289</a> Extract information from Exception objects in the heap dumps
 			</li>
 
-			<li class="li">Memory Analyzer can now work with Java virtual machines, version 9 and version 10,
-			as well as 1.8. Dumps from JVMs versions 1.5, 1.6 and 1.7 are still handled.
-			Memory Analyzer has been tested with JVMs of the
-			following types:
-			<ul class="ul">
-			<li class="li">Oracle JVMs</li>
-
-			<li class="li">OpenJDK JVMs</li>
-
-			<li class="li">IBM JVMs</li>
-
-			<li class="li">OpenJ9 JVMs</li>
-
-			</ul>
-
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=380600">380600</a> Resave Heap Dump without Unreachable Objects
 			</li>
 
-			<li class="li">Fixes for new Java 9 string format</li>
-
-			<li class="li">Acquire heap dumps - various improvements:
-			<ul class="ul">
-			<li class="li">Attach API provider now works using <samp class="ph codeph">com.sun.tools.attach</samp>
-			allowing it to work with Oracle JVMs and IBM JVMs, version 1.8 SR5 and later.
-			Earlier IBM JVMs continue to work using <samp class="ph codeph">com.ibm.tools.attach</samp></li>
-
-			<li class="li">Sort columns of PID and provider</li>
-
-			<li class="li">Resizing of columns with window</li>
-
-			<li class="li">More help, including links to provider help</li>
-
-			<li class="li">Processes unavailable for dumps marked in <em class="ph i">italics</em></li>
-
-			<li class="li">Attach API provide can generate HPROF dumps for Oracle and OpenJDK JVMS
-			using HotSpot MX bean.</li>
-
-			<li class="li">Configure Heap Dump providers page jumps to appropriate provider when
-			selected from a process.</li>
-
-			</ul>
-
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=519274">519274</a> Redacted Binary or PHD dump so as to protect privacy data
 			</li>
 
-			<li class="li">Equinox Bundle Explorer now handles more recent Eclipse versions.</li>
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=538953">538953</a> Create an option for DTFJIndexBuilder to suppress native class sizes
+			</li>
 
-			<li class="li">More collections handled by collection queries, including collections from Java 9 and Java 10.</li>
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=539750">539750</a> java.util.ConcurrentModificationException with Calculate precise retained size and sort
+			</li>
 
-			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=520908">520908</a>: Invalid thread object in ThreadOverviewQuery causes whole query to fail</li>
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=541245">541245</a> Exceptions with result filtering
+			</li>
 
-			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=521999">521999</a>: pString values not displayed analyzing some IBM core dumps</li>
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=541286">541286</a> Missing shallow heap size values in comparison tables
+			</li>
 
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=541539">541539</a> Simple batch mode comparison of two snapshots
+			</li>
+
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=543045">543045</a> Eclipse MAT does not show complete actual heap size(Heap dump size) on overview tab.
+			</li>
+
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=537579">537579</a> ArrayIndexOutOfBoundsException in HashMapObjectLong.resize
+			</li>
+
+			<li class="li">Fix for <a class="xref" href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=539751">539751</a> Unhandled event loop exception - InjectionException - WidgetMethodHandler is not handled for for command Command Copy
+			</li>
+ 
 			</ul>
 
 		</div>
 
 		
-		<div class="section"><h2 class="title sectiontitle">New and Noteworthy for Memory Analyzer 1.7</h2>
+		<div class="section"><h2 class="title sectiontitle">New and Noteworthy for Memory Analyzer 1.8</h2>
 			
 			<p class="p">
-				The New and Noteworthy document for version 1.7 is available 
-				<a class="xref" href="http://www.eclipse.org/mat/1.7.0/noteworthy.html">here</a>.
+				The New and Noteworthy document for version 1.8 is available 
+				<a class="xref" href="http://www.eclipse.org/mat/1.8.0/noteworthy.html">here</a>.
 			</p>
 
 		</div>
diff --git a/plugins/org.eclipse.mat.ui.help/pom.xml b/plugins/org.eclipse.mat.ui.help/pom.xml
index f287ac7..e4a614c 100644
--- a/plugins/org.eclipse.mat.ui.help/pom.xml
+++ b/plugins/org.eclipse.mat.ui.help/pom.xml
Binary files differ
diff --git a/plugins/org.eclipse.mat.ui.help/tasks/analyzingfinalizer.dita b/plugins/org.eclipse.mat.ui.help/tasks/analyzingfinalizer.dita
index 0c84902..e67ced1 100644
--- a/plugins/org.eclipse.mat.ui.help/tasks/analyzingfinalizer.dita
+++ b/plugins/org.eclipse.mat.ui.help/tasks/analyzingfinalizer.dita
@@ -53,7 +53,7 @@
 								<ul>

 									<li>it is blocking</li>

 									<li>it is long running</li>

-									<li> it the finalizer queue was or is still full.</li>

+									<li>the finalizer queue was or is still full.</li>

 								</ul>

 								<p> Use the finalizer queue query to check the queue.</p>

 							</entry>

@@ -72,6 +72,13 @@
 									<li> The application made use of too many objects with

 										finalize() which are queued up in memory.</li>

 								</ul>

+								<p>Note: On J9 JVM-based dumps (e.g. IBM Java, OpenJ9), this

+								   list shows objects waiting to be finalized and those

+								   which have already been finalized and are waiting to be

+								   garbage collected. This query does not provide a way to

+								   differentiate the two (because DTFJ doesn't), although you may 

+								   be able to differentiate based on object fields

+								   (e.g. a "closed" boolean field, etc.).</p>

 								<p> Additionally a class-level summary of the objects is provided</p>

 							</entry>

 						</row>

diff --git a/plugins/org.eclipse.mat.ui.help/tasks/analyzingfinalizer.html b/plugins/org.eclipse.mat.ui.help/tasks/analyzingfinalizer.html
index 88381f1..7d091e5 100644
--- a/plugins/org.eclipse.mat.ui.help/tasks/analyzingfinalizer.html
+++ b/plugins/org.eclipse.mat.ui.help/tasks/analyzingfinalizer.html
@@ -53,7 +53,7 @@
 
 									<li class="li">it is long running</li>
 
-									<li class="li"> it the finalizer queue was or is still full.</li>
+									<li class="li">the finalizer queue was or is still full.</li>
 
 								</ul>
 
@@ -82,6 +82,14 @@
 
 								</ul>
 
+								<p class="p">Note: On J9 JVM-based dumps (e.g. IBM Java, OpenJ9), this
+								   list shows objects waiting to be finalized and those
+								   which have already been finalized and are waiting to be
+								   garbage collected. This query does not provide a way to
+								   differentiate the two (because DTFJ doesn't), although you may 
+								   be able to differentiate based on object fields
+								   (e.g. a "closed" boolean field, etc.).</p>
+
 								<p class="p"> Additionally a class-level summary of the objects is provided</p>
 
 							</td>
diff --git a/plugins/org.eclipse.mat.ui.help/tasks/analyzingjavacollectionusage.dita b/plugins/org.eclipse.mat.ui.help/tasks/analyzingjavacollectionusage.dita
index a2d2551..3c45367 100644
--- a/plugins/org.eclipse.mat.ui.help/tasks/analyzingjavacollectionusage.dita
+++ b/plugins/org.eclipse.mat.ui.help/tasks/analyzingjavacollectionusage.dita
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>

 <!--

-    Copyright (c) 2008, 2010 SAP AG.

+    Copyright (c) 2008, 2019 SAP AG and IBM Corporation.

     All rights reserved. This program and the accompanying materials

     are made available under the terms of the Eclipse Public License v1.0

     which accompanies this distribution, and is available at

@@ -8,6 +8,7 @@
    

     Contributors:

         SAP AG - initial API and implementation

+        IBM Corporation - additional collection classes

  -->

 <!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "task.dtd" >

 <task id="task_analyzingjavacollectionusage" xml:lang="en-us">

@@ -16,7 +17,7 @@
 		<copyright>

 			<copyryear year=""></copyryear>

 			<copyrholder>

-				Copyright (c) 2008, 2010 SAP AG and others.

+				Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.

 				All rights reserved. This program and the accompanying materials

 				are made available under the terms of the Eclipse Public License v1.0

 				which accompanies this distribution, and is available at

@@ -97,6 +98,9 @@
 										<codeblock>java.util.Collections$EmptySet</codeblock>

 									</li>

 									<li>

+										<codeblock>java.util.Collections$SetFromMap</codeblock>

+									</li>

+									<li>

 										<codeblock>java.util.Collections$SingletonList</codeblock>

 									</li>

 									<li>

@@ -148,6 +152,12 @@
 										<codeblock>java.util.concurrent.SynchronousQueue</codeblock>

 									</li>

 									<li>

+										<codeblock>java.util.EnumMap</codeblock>

+									</li>

+									<li>

+										<codeblock>java.util.EnumSet</codeblock>

+									</li>

+									<li>

 										<codeblock>java.util.HashMap</codeblock>

 									</li>

 									<li>

@@ -157,6 +167,9 @@
 										<codeblock>java.util.Hashtable</codeblock>

 									</li>

 									<li>

+										<codeblock>java.util.IdentityHashMap</codeblock>

+									</li>

+									<li>

 										<codeblock>java.util.ImmutableCollections$List0</codeblock>

 									</li>

 									<li>

@@ -238,6 +251,9 @@
 										<codeblock>java.util.Collections$EmptySet</codeblock>

 									</li>

 									<li>

+										<codeblock>java.util.Collections$SetFromMap</codeblock>

+									</li>

+									<li>

 										<codeblock>java.util.Collections$SingletonList</codeblock>

 									</li>

 									<li>

@@ -304,6 +320,12 @@
 										<codeblock>java.util.concurrent.SynchronousQueue</codeblock>

 									</li>

 									<li>

+										<codeblock>java.util.EnumMap</codeblock>

+									</li>

+									<li>

+										<codeblock>java.util.EnumSet</codeblock>

+									</li>

+									<li>

 										<codeblock>java.util.HashMap</codeblock>

 									</li>

 									<li>

@@ -437,15 +459,9 @@
 										<codeblock>java.util.concurrent.ConcurrentHashMap$Segment</codeblock>

 									</li>

 									<li>

-										<codeblock>java.util.HashMap</codeblock>

-									</li>

-									<li>

 										<codeblock>java.util.HashSet</codeblock>

 									</li>

 									<li>

-										<codeblock>java.util.Hashtable</codeblock>

-									</li>

-									<li>

 										<codeblock>java.util.concurrent.ConcurrentHashMap</codeblock>

 									</li>

 									<li>

@@ -455,13 +471,10 @@
 										<codeblock>java.util.concurrent.ConcurrentSkipListSet</codeblock>

 									</li>

 									<li>

-										<codeblock>java.util.Collections$CheckedSet</codeblock>

-									</li>

-									<li>

 										<codeblock>java.util.Collections$CheckedMap</codeblock>

 									</li>

 									<li>

-										<codeblock>java.util.Collections$UnmodifiableMap</codeblock>

+										<codeblock>java.util.Collections$CheckedSet</codeblock>

 									</li>

 									<li>

 										<codeblock>java.util.Collections$SynchronizedMap</codeblock>

diff --git a/plugins/org.eclipse.mat.ui.help/tasks/analyzingjavacollectionusage.html b/plugins/org.eclipse.mat.ui.help/tasks/analyzingjavacollectionusage.html
index 9b35dc8..b0895e3 100644
--- a/plugins/org.eclipse.mat.ui.help/tasks/analyzingjavacollectionusage.html
+++ b/plugins/org.eclipse.mat.ui.help/tasks/analyzingjavacollectionusage.html
@@ -6,8 +6,8 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <meta name="DC.Type" content="task"/>
 <meta name="DC.Title" content="Analyzing Java Collection Usage"/>
-<meta name="copyright" content="Copyright (c) 2008, 2010 SAP AG and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
-<meta name="DC.Rights.Owner" content="Copyright (c) 2008, 2010 SAP AG and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
+<meta name="copyright" content="Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
+<meta name="DC.Rights.Owner" content="Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
 <meta name="DC.Format" content="XHTML"/>
 <meta name="DC.Identifier" content="task_analyzingjavacollectionusage"/>
 <meta name="DC.Language" content="en-us"/>
@@ -126,6 +126,11 @@
 									</li>
 
 									<li class="li">
+										<pre class="pre codeblock">java.util.Collections$SetFromMap</pre>
+
+									</li>
+
+									<li class="li">
 										<pre class="pre codeblock">java.util.Collections$SingletonList</pre>
 
 									</li>
@@ -211,6 +216,16 @@
 									</li>
 
 									<li class="li">
+										<pre class="pre codeblock">java.util.EnumMap</pre>
+
+									</li>
+
+									<li class="li">
+										<pre class="pre codeblock">java.util.EnumSet</pre>
+
+									</li>
+
+									<li class="li">
 										<pre class="pre codeblock">java.util.HashMap</pre>
 
 									</li>
@@ -226,6 +241,11 @@
 									</li>
 
 									<li class="li">
+										<pre class="pre codeblock">java.util.IdentityHashMap</pre>
+
+									</li>
+
+									<li class="li">
 										<pre class="pre codeblock">java.util.ImmutableCollections$List0</pre>
 
 									</li>
@@ -357,6 +377,11 @@
 									</li>
 
 									<li class="li">
+										<pre class="pre codeblock">java.util.Collections$SetFromMap</pre>
+
+									</li>
+
+									<li class="li">
 										<pre class="pre codeblock">java.util.Collections$SingletonList</pre>
 
 									</li>
@@ -467,6 +492,16 @@
 									</li>
 
 									<li class="li">
+										<pre class="pre codeblock">java.util.EnumMap</pre>
+
+									</li>
+
+									<li class="li">
+										<pre class="pre codeblock">java.util.EnumSet</pre>
+
+									</li>
+
+									<li class="li">
 										<pre class="pre codeblock">java.util.HashMap</pre>
 
 									</li>
@@ -678,26 +713,11 @@
 									</li>
 
 									<li class="li">
-										<pre class="pre codeblock">java.util.HashMap</pre>
-
-									</li>
-
-									<li class="li">
 										<pre class="pre codeblock">java.util.HashSet</pre>
 
 									</li>
 
 									<li class="li">
-										<pre class="pre codeblock">java.util.Hashtable</pre>
-
-									</li>
-
-									<li class="li">
-										<pre class="pre codeblock">java.util.IdentityHashMap</pre>
-
-									</li>
-
-									<li class="li">
 										<pre class="pre codeblock">java.util.concurrent.ConcurrentHashMap</pre>
 
 									</li>
@@ -713,17 +733,12 @@
 									</li>
 
 									<li class="li">
-										<pre class="pre codeblock">java.util.Collections$CheckedSet</pre>
-
-									</li>
-
-									<li class="li">
 										<pre class="pre codeblock">java.util.Collections$CheckedMap</pre>
 
 									</li>
 
 									<li class="li">
-										<pre class="pre codeblock">java.util.Collections$UnmodifiableMap</pre>
+										<pre class="pre codeblock">java.util.Collections$CheckedSet</pre>
 
 									</li>
 
diff --git a/plugins/org.eclipse.mat.ui.help/tasks/batch.dita b/plugins/org.eclipse.mat.ui.help/tasks/batch.dita
new file mode 100644
index 0000000..9f2fea7
--- /dev/null
+++ b/plugins/org.eclipse.mat.ui.help/tasks/batch.dita
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<!--

+    Copyright (c) 2019 IBM Corporation.

+    All rights reserved. This program and the accompanying materials

+    are made available under the terms of the Eclipse Public License v1.0

+    which accompanies this distribution, and is available at

+    http://www.eclipse.org/legal/epl-v10.html

+   

+    Contributors:

+        Andrew Johnson/IBM - initial API and implementation

+ -->

+<!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "task.dtd" >

+<task id="task_batch" xml:lang="en-us">

+	<title>Batch mode</title>

+	<prolog>

+		<copyright>

+			<copyryear year=""></copyryear>

+			<copyrholder>

+				Copyright (c) 2019 IBM Corporation.

+			    All rights reserved. This program and the accompanying materials

+			    are made available under the terms of the Eclipse Public License v1.0

+			    which accompanies this distribution, and is available at

+			    http://www.eclipse.org/legal/epl-v10.html

+			</copyrholder>

+		</copyright>

+	</prolog>

+

+	<taskbody>

+		<context>

+			<p>Memory Analyzer can be operated in batch mode to process heap dumps

+			without user input.</p>

+		</context>

+		<steps>

+			<step>

+				<note>On Windows, use <keyword>.\mat\ParseHeapDump.bat</keyword> instead of <keyword>./mat/ParseHeapDump.sh</keyword></note>

+				<cmd>Run <cmdname>./mat/ParseHeapDump.sh</cmdname> <parmname>myheapdump.hprof</parmname> <parmname>org.eclipse.mat.api:suspects</parmname>

+				</cmd>

+				<choices>

+					<choice>For a simple suspects report use <parmname>org.eclipse.mat.api:suspects</parmname></choice>

+					<choice>For an overview report use <parmname>org.eclipse.mat.api:overview</parmname></choice>

+					<choice>For a report on memory usage by component use <parmname>org.eclipse.mat.api:top_components</parmname></choice>

+					<choice>To compare two heap dumps use<cmdname>./mat/ParseHeapDump.sh</cmdname> <parmname>myheapdump.hprof</parmname> <option>-snapshot2=</option><parmname>myheapdump2.hprof</parmname> <parmname>org.eclipse.mat.api:compare</parmname></choice>					

+				</choices>

+				<stepresult>

+					<msgblock>

+Task: Parsing myheapdump.hprof

+[Task: Parsing .\Downloads\myheapdump.hprof

+[

+Subtask: Scanning .\Downloads\myheapdump.hprof

+[.................

+[INFO] Detected compressed references, because with uncompressed 64-bit references the array at 0x5c4bd4258 would overlap the array at 0x5c4bd4230

+[....................

+[INFO] Wrote threads call stacks to .\Downloads\myheapdump.threads

+[....................

+[INFO] Heap .\Downloads\myheapdump.hprof contains 116,716 objects

+[....................

+Subtask: Extracting objects from .\Downloads\myheapdump.hprof

+[...................................................................................Task: Removing unreachable objects

+[

+Subtask: Searching for unreachable objects

+[

+Subtask: Marking reachable objects

+[.

+Subtask: Re-indexing objects

+[..

+Subtask: Re-indexing classes

+[...

+Subtask: Writing .\Downloads\myheapdump.idx.index

+[....

+Subtask: Writing .\Downloads\myheapdump.o2c.index

+[.....

+Subtask: Writing .\Downloads\myheapdump.a2s.index

+[......

+Subtask: Re-indexing outbound index

+[.......

+Subtask: Writing .\Downloads\myheapdump.inbound.index

+[........

+Subtask: Writing .\Downloads\myheapdump.outbound.index

+[.........

+Subtask: Writing .\Downloads\myheapdump.o2hprof.index

+[.........Task: Calculating Dominator Tree

+[

+Subtask: Dominator Tree calculation

+[

+Subtask: Depth-first search

+[....................

+Subtask: Computing dominators

+[..............................................

+Subtask: Calculate retained sizes

+[............................................................

+Subtask: Create dominators index file

+[................................................................................]

+

+Subtask: Test 'Heap Dump Overview' of section 'System Overview'

+[

+Subtask: Test 'System Properties' of section 'System Overview'

+[

+Subtask: Extracting Key Value Pairs...

+[

+Subtask: Test 'Thread Overview' of section 'System Overview'

+[

+Subtask: Searching Threads...

+[

+Subtask: Test 'Top Consumers' of section 'System Overview'

+[

+Subtask: Creating histogram

+[

+Subtask: Grouping by package

+[

+Subtask: Test 'Biggest Objects (Overview)' of section 'Top Consumers'

+[

+Subtask: Test 'Biggest Objects' of section 'Top Consumers'

+[

+Subtask: Test 'Biggest Top-Level Dominator Classes (Overview)' of section 'Top Consumers'

+[

+Subtask: Test 'Biggest Top-Level Dominator Classes' of section 'Top Consumers'

+[

+Subtask: Test 'Biggest Top-Level Dominator Class Loaders (Overview)' of section 'Top Consumers'

+[

+Subtask: Test 'Biggest Top-Level Dominator Class Loaders' of section 'Top Consumers'

+[

+Subtask: Test 'Biggest Top-Level Dominator Packages' of section 'Top Consumers'

+[

+Subtask: Test 'Class Histogram' of section 'System Overview'

+[

+Subtask: Test 'Leaks' of section 'Leak Suspects'

+[

+Subtask: Finding problem suspects

+[

+Subtask: Searching suspicious single objects ...

+[

+Subtask: Searching suspicious groups of objects ...

+[

+Subtask: building histogram

+[

+Subtask: Preparing results

+[

+Subtask: building histogram

+[

+Subtask: building histogram

+[

+Subtask: Finding paths

+[

+Subtask: Test 'Overview' of section 'Leaks'

+[

+Subtask: Test 'Problem Suspect 1' of section 'Leaks'

+[

+Subtask: Test 'Description' of section 'Problem Suspect 1'

+[

+Subtask: Test 'Shortest Paths To the Accumulation Point' of section 'Problem Suspect 1'

+[

+Subtask: Test 'Shortest Paths To the Accumulation Point' of section 'Problem Suspect 1'

+[

+Subtask: Test 'Accumulated Objects in Dominator Tree' of section 'Problem Suspect 1'

+[

+Subtask: Test 'Accumulated Objects in Dominator Tree' of section 'Problem Suspect 1'

+[

+Subtask: Test 'Accumulated Objects by Class in Dominator Tree' of section 'Problem Suspect 1'

+[

+Subtask: Test 'Accumulated Objects by Class in Dominator Tree' of section 'Problem Suspect 1'

+[

+Subtask: Test 'All Accumulated Objects by Class' of section 'Problem Suspect 1'

+[

+Subtask: Test 'All Accumulated Objects by Class' of section 'Problem Suspect 1'

+[]

+					</msgblock>

+				</stepresult>

+			</step>

+			<step>

+				<cmd>

+					Unzip the report <parmname>myheapdump_Leak_Suspects.zip</parmname>

+				</cmd>

+			</step>

+			<step>

+				<cmd>

+					View the <parmname>index.html</parmname>

+				</cmd>

+			</step>

+		</steps>

+		<result>

+			<p>The result is a HTML report.</p>

+		</result>

+	</taskbody>

+</task>
\ No newline at end of file
diff --git a/plugins/org.eclipse.mat.ui.help/tasks/batch.html b/plugins/org.eclipse.mat.ui.help/tasks/batch.html
new file mode 100644
index 0000000..bc8699e
--- /dev/null
+++ b/plugins/org.eclipse.mat.ui.help/tasks/batch.html
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html
+  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xml:lang="en-us" lang="en-us">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<meta name="DC.Type" content="task"/>
+<meta name="DC.Title" content="Batch mode"/>
+<meta name="copyright" content="Copyright (c) 2019 IBM Corporation. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
+<meta name="DC.Rights.Owner" content="Copyright (c) 2019 IBM Corporation. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html " type="primary"/>
+<meta name="DC.Format" content="XHTML"/>
+<meta name="DC.Identifier" content="task_batch"/>
+<meta name="DC.Language" content="en-us"/>
+<link rel="stylesheet" type="text/css" href="../styles/commonltr.css"/>
+<title>Batch mode</title>
+</head>
+<body id="task_batch">
+
+
+	<h1 class="title topictitle1">Batch mode</h1>
+
+	
+
+	<div class="body taskbody">
+		<div class="section context">
+			<p class="p">Memory Analyzer can be operated in batch mode to process heap dumps
+			without user input.</p>
+
+		</div>
+
+		<ol class="ol steps"><li class="li step stepexpand">
+				<div class="note note"><span class="notetitle">Note:</span> On Windows, use <span class="keyword">.\mat\ParseHeapDump.bat</span> instead of <span class="keyword">./mat/ParseHeapDump.sh</span></div>
+
+				<span class="ph cmd">Run <span class="keyword cmdname">./mat/ParseHeapDump.sh</span> <span class="keyword parmname">myheapdump.hprof</span> <span class="keyword parmname">org.eclipse.mat.api:suspects</span>
+				</span>
+				<ul class="ul choices">
+					<li class="li choice">For a simple suspects report use <span class="keyword parmname">org.eclipse.mat.api:suspects</span></li>
+
+					<li class="li choice">For an overview report use <span class="keyword parmname">org.eclipse.mat.api:overview</span></li>
+
+					<li class="li choice">For a report on memory usage by component use <span class="keyword parmname">org.eclipse.mat.api:top_components</span></li>
+
+					<li class="li choice">To compare two heap dumps use<span class="keyword cmdname">./mat/ParseHeapDump.sh</span> <span class="keyword parmname">myheapdump.hprof</span> <span class="keyword option">-snapshot2=</span><span class="keyword parmname">myheapdump2.hprof</span> <span class="keyword parmname">org.eclipse.mat.api:compare</span></li>
+					
+				</ul>
+
+				<div class="itemgroup stepresult">
+					<pre class="pre msgblock">
+Task: Parsing myheapdump.hprof
+[Task: Parsing .\Downloads\myheapdump.hprof
+[
+Subtask: Scanning .\Downloads\myheapdump.hprof
+[.................
+[INFO] Detected compressed references, because with uncompressed 64-bit references the array at 0x5c4bd4258 would overlap the array at 0x5c4bd4230
+[....................
+[INFO] Wrote threads call stacks to .\Downloads\myheapdump.threads
+[....................
+[INFO] Heap .\Downloads\myheapdump.hprof contains 116,716 objects
+[....................
+Subtask: Extracting objects from .\Downloads\myheapdump.hprof
+[...................................................................................Task: Removing unreachable objects
+[
+Subtask: Searching for unreachable objects
+[
+Subtask: Marking reachable objects
+[.
+Subtask: Re-indexing objects
+[..
+Subtask: Re-indexing classes
+[...
+Subtask: Writing .\Downloads\myheapdump.idx.index
+[....
+Subtask: Writing .\Downloads\myheapdump.o2c.index
+[.....
+Subtask: Writing .\Downloads\myheapdump.a2s.index
+[......
+Subtask: Re-indexing outbound index
+[.......
+Subtask: Writing .\Downloads\myheapdump.inbound.index
+[........
+Subtask: Writing .\Downloads\myheapdump.outbound.index
+[.........
+Subtask: Writing .\Downloads\myheapdump.o2hprof.index
+[.........Task: Calculating Dominator Tree
+[
+Subtask: Dominator Tree calculation
+[
+Subtask: Depth-first search
+[....................
+Subtask: Computing dominators
+[..............................................
+Subtask: Calculate retained sizes
+[............................................................
+Subtask: Create dominators index file
+[................................................................................]
+
+Subtask: Test 'Heap Dump Overview' of section 'System Overview'
+[
+Subtask: Test 'System Properties' of section 'System Overview'
+[
+Subtask: Extracting Key Value Pairs...
+[
+Subtask: Test 'Thread Overview' of section 'System Overview'
+[
+Subtask: Searching Threads...
+[
+Subtask: Test 'Top Consumers' of section 'System Overview'
+[
+Subtask: Creating histogram
+[
+Subtask: Grouping by package
+[
+Subtask: Test 'Biggest Objects (Overview)' of section 'Top Consumers'
+[
+Subtask: Test 'Biggest Objects' of section 'Top Consumers'
+[
+Subtask: Test 'Biggest Top-Level Dominator Classes (Overview)' of section 'Top Consumers'
+[
+Subtask: Test 'Biggest Top-Level Dominator Classes' of section 'Top Consumers'
+[
+Subtask: Test 'Biggest Top-Level Dominator Class Loaders (Overview)' of section 'Top Consumers'
+[
+Subtask: Test 'Biggest Top-Level Dominator Class Loaders' of section 'Top Consumers'
+[
+Subtask: Test 'Biggest Top-Level Dominator Packages' of section 'Top Consumers'
+[
+Subtask: Test 'Class Histogram' of section 'System Overview'
+[
+Subtask: Test 'Leaks' of section 'Leak Suspects'
+[
+Subtask: Finding problem suspects
+[
+Subtask: Searching suspicious single objects ...
+[
+Subtask: Searching suspicious groups of objects ...
+[
+Subtask: building histogram
+[
+Subtask: Preparing results
+[
+Subtask: building histogram
+[
+Subtask: building histogram
+[
+Subtask: Finding paths
+[
+Subtask: Test 'Overview' of section 'Leaks'
+[
+Subtask: Test 'Problem Suspect 1' of section 'Leaks'
+[
+Subtask: Test 'Description' of section 'Problem Suspect 1'
+[
+Subtask: Test 'Shortest Paths To the Accumulation Point' of section 'Problem Suspect 1'
+[
+Subtask: Test 'Shortest Paths To the Accumulation Point' of section 'Problem Suspect 1'
+[
+Subtask: Test 'Accumulated Objects in Dominator Tree' of section 'Problem Suspect 1'
+[
+Subtask: Test 'Accumulated Objects in Dominator Tree' of section 'Problem Suspect 1'
+[
+Subtask: Test 'Accumulated Objects by Class in Dominator Tree' of section 'Problem Suspect 1'
+[
+Subtask: Test 'Accumulated Objects by Class in Dominator Tree' of section 'Problem Suspect 1'
+[
+Subtask: Test 'All Accumulated Objects by Class' of section 'Problem Suspect 1'
+[
+Subtask: Test 'All Accumulated Objects by Class' of section 'Problem Suspect 1'
+[]
+					</pre>
+
+				</div>
+			</li>
+<li class="li step stepexpand">
+				<span class="ph cmd">
+					Unzip the report <span class="keyword parmname">myheapdump_Leak_Suspects.zip</span>
+				</span>
+			</li>
+<li class="li step stepexpand">
+				<span class="ph cmd">
+					View the <span class="keyword parmname">index.html</span>
+				</span>
+			</li>
+</ol>
+
+		<div class="section result">
+			<p class="p">The result is a HTML report.</p>
+
+		</div>
+
+	</div>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.mat.ui.help/toc.ditamap b/plugins/org.eclipse.mat.ui.help/toc.ditamap
index 83c6338..73fad68 100644
--- a/plugins/org.eclipse.mat.ui.help/toc.ditamap
+++ b/plugins/org.eclipse.mat.ui.help/toc.ditamap
@@ -27,7 +27,8 @@
 		<topicref href="tasks/bundleregistry.dita" type="task" />

 		<topicref href="tasks/comparingdata.dita" type="task" />

 		<topicref href="tasks/exportdata.dita" type="task" />
-		<topicref href="tasks/exportdump.dita" type="task" />

+		<topicref href="tasks/exportdump.dita" type="task" />
+		<topicref href="tasks/batch.dita" type="task" />

 		<topicref href="tasks/configure_mat.dita" type="task" />
 	</topichead>

 	<topichead navtitle="Reference">
diff --git a/plugins/org.eclipse.mat.ui.help/toc.xml b/plugins/org.eclipse.mat.ui.help/toc.xml
index d1fe988..b6d9653 100644
--- a/plugins/org.eclipse.mat.ui.help/toc.xml
+++ b/plugins/org.eclipse.mat.ui.help/toc.xml
@@ -1,3 +1,3 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?NLS TYPE="org.eclipse.help.toc"?>
-<toc label="Memory Analyzer" topic="welcome.html"><topic label="Introduction" href="welcome.html"/><topic label="Getting Started"><topic label="Basic Tutorial" href="gettingstarted/basictutorial.html"/></topic><topic label="Concepts"><topic label="Heap Dump" href="concepts/heapdump.html"/><topic label="Reachability" href="concepts/reachability.html"/><topic label="Shallow vs. Retained Heap" href="concepts/shallowretainedheap.html"/><topic label="Dominator Tree" href="concepts/dominatortree.html"/><topic label="Garbage Collection Roots" href="concepts/gcroots.html"/></topic><topic label="Tasks"><topic label="Acquiring Heap Dumps" href="tasks/acquiringheapdump.html"/><topic label="Installing IBM DTFJ feature for IBM dumps" href="tasks/installDTFJ.html"/><topic label="Running Leak Suspect Report" href="tasks/runningleaksuspectreport.html"/><topic label="List the Biggest Objects" href="tasks/listbiggestobjects.html"/><topic label="Finding Responsible Objects" href="tasks/findingresponsibleobjects.html"/><topic label="Querying Heap Objects (OQL)" href="tasks/queryingheapobjects.html"/><topic label="Analyze Class Loader" href="tasks/analyzingclassloader.html"/><topic label="Analyzing Threads" href="tasks/analyzingthreads.html"/><topic label="Analyzing Java Collection Usage" href="tasks/analyzingjavacollectionusage.html"/><topic label="Analyzing Finalizer" href="tasks/analyzingfinalizer.html"/><topic label="Eclipse Equinox Bundle Registry" href="tasks/bundleregistry.html"/><topic label="Comparing Objects" href="tasks/comparingdata.html"/><topic label="Export Data" href="tasks/exportdata.html"/><topic label="Export Heap Dump" href="tasks/exportdump.html"/><topic label="Memory Analyzer Configuration" href="tasks/configure_mat.html"/></topic><topic label="Reference"><topic label="Inspections"><topic label="Leak Identification"><topic label="Component Report" href="reference/inspections/component_report.html"/></topic><topic label="Immediate Dominators" href="reference/inspections/immediate_dominators.html"/><topic label="Group by Value" href="reference/inspections/group_by_value.html"/><topic label="Path to GC Roots" href="reference/inspections/path_to_gc_roots.html"/><topic label="Retained Set" href="reference/inspections/retained_set.html"/><topic label="Top Consumers" href="reference/inspections/top_consumers.html"/><topic label="Unreachable objects" href="reference/inspections/unreachable_objects.html"/></topic><topic label="Query Matrix" href="reference/querymatrix.html"><topic label="Finding Memory Leak" href="reference/findingmemoryleak.html"/><topic label="Analyzing Memory Consumption" href="reference/analyzingmemoryconsumption.html"/></topic><topic label="OQL Syntax" href="reference/oqlsyntax.html"><topic label="SELECT Clause" href="reference/oqlsyntaxselect.html"/><topic label="FROM Clause" href="reference/oqlsyntaxfrom.html"/><topic label="WHERE Clause" href="reference/oqlsyntaxwhere.html"/><topic label="Property Accessors" href="reference/propertyaccessors.html"/><topic label="BNF for the Object Query Language" href="reference/bnfofoql.html"/></topic><topic label="Selecting Queries" href="reference/selectingqueries.html"/><topic label="Icons Assist" href="reference/iconassist.html"/><topic label="Tips and Tricks" href="reference/tipsandtricks.html"/><topic label="Extending Memory Analyzer" href="reference/extendingmat.html"/><topic label="API Reference" href="doc/index.html"/></topic><topic label="New and Noteworthy" href="noteworthy.html"/><topic label="Legal" href="legal.html"/></toc>
\ No newline at end of file
+<toc label="Memory Analyzer" topic="welcome.html"><topic label="Introduction" href="welcome.html"/><topic label="Getting Started"><topic label="Basic Tutorial" href="gettingstarted/basictutorial.html"/></topic><topic label="Concepts"><topic label="Heap Dump" href="concepts/heapdump.html"/><topic label="Reachability" href="concepts/reachability.html"/><topic label="Shallow vs. Retained Heap" href="concepts/shallowretainedheap.html"/><topic label="Dominator Tree" href="concepts/dominatortree.html"/><topic label="Garbage Collection Roots" href="concepts/gcroots.html"/></topic><topic label="Tasks"><topic label="Acquiring Heap Dumps" href="tasks/acquiringheapdump.html"/><topic label="Installing IBM DTFJ feature for IBM dumps" href="tasks/installDTFJ.html"/><topic label="Running Leak Suspect Report" href="tasks/runningleaksuspectreport.html"/><topic label="List the Biggest Objects" href="tasks/listbiggestobjects.html"/><topic label="Finding Responsible Objects" href="tasks/findingresponsibleobjects.html"/><topic label="Querying Heap Objects (OQL)" href="tasks/queryingheapobjects.html"/><topic label="Analyze Class Loader" href="tasks/analyzingclassloader.html"/><topic label="Analyzing Threads" href="tasks/analyzingthreads.html"/><topic label="Analyzing Java Collection Usage" href="tasks/analyzingjavacollectionusage.html"/><topic label="Analyzing Finalizer" href="tasks/analyzingfinalizer.html"/><topic label="Eclipse Equinox Bundle Registry" href="tasks/bundleregistry.html"/><topic label="Comparing Objects" href="tasks/comparingdata.html"/><topic label="Export Data" href="tasks/exportdata.html"/><topic label="Export Heap Dump" href="tasks/exportdump.html"/><topic label="Batch mode" href="tasks/batch.html"/><topic label="Memory Analyzer Configuration" href="tasks/configure_mat.html"/></topic><topic label="Reference"><topic label="Inspections"><topic label="Leak Identification"><topic label="Component Report" href="reference/inspections/component_report.html"/></topic><topic label="Immediate Dominators" href="reference/inspections/immediate_dominators.html"/><topic label="Group by Value" href="reference/inspections/group_by_value.html"/><topic label="Path to GC Roots" href="reference/inspections/path_to_gc_roots.html"/><topic label="Retained Set" href="reference/inspections/retained_set.html"/><topic label="Top Consumers" href="reference/inspections/top_consumers.html"/><topic label="Unreachable objects" href="reference/inspections/unreachable_objects.html"/></topic><topic label="Query Matrix" href="reference/querymatrix.html"><topic label="Finding Memory Leak" href="reference/findingmemoryleak.html"/><topic label="Analyzing Memory Consumption" href="reference/analyzingmemoryconsumption.html"/></topic><topic label="OQL Syntax" href="reference/oqlsyntax.html"><topic label="SELECT Clause" href="reference/oqlsyntaxselect.html"/><topic label="FROM Clause" href="reference/oqlsyntaxfrom.html"/><topic label="WHERE Clause" href="reference/oqlsyntaxwhere.html"/><topic label="Property Accessors" href="reference/propertyaccessors.html"/><topic label="BNF for the Object Query Language" href="reference/bnfofoql.html"/></topic><topic label="Selecting Queries" href="reference/selectingqueries.html"/><topic label="Icons Assist" href="reference/iconassist.html"/><topic label="Tips and Tricks" href="reference/tipsandtricks.html"/><topic label="Extending Memory Analyzer" href="reference/extendingmat.html"/><topic label="API Reference" href="doc/index.html"/></topic><topic label="New and Noteworthy" href="noteworthy.html"/><topic label="Legal" href="legal.html"/></toc>
\ No newline at end of file
diff --git a/plugins/org.eclipse.mat.ui.help/welcome.dita b/plugins/org.eclipse.mat.ui.help/welcome.dita
index 192bd0c..20027ab 100644
--- a/plugins/org.eclipse.mat.ui.help/welcome.dita
+++ b/plugins/org.eclipse.mat.ui.help/welcome.dita
@@ -73,6 +73,7 @@
 		<p><xref href="tasks/comparingdata.dita" /></p>
 		<p><xref href="tasks/exportdata.dita" /></p>
 		<p><xref href="tasks/exportdump.dita" /></p>
+		<p><xref href="tasks/batch.dita" /></p>
 		<p><xref href="tasks/configure_mat.dita" /></p>
 	</section>
 
diff --git a/plugins/org.eclipse.mat.ui.help/welcome.html b/plugins/org.eclipse.mat.ui.help/welcome.html
index 3fb7886..85893b1 100644
--- a/plugins/org.eclipse.mat.ui.help/welcome.html
+++ b/plugins/org.eclipse.mat.ui.help/welcome.html
@@ -91,6 +91,8 @@
 
 		<p class="p"><a class="xref" href="tasks/exportdump.html">Export Heap Dump</a></p>
 
+		<p class="p"><a class="xref" href="tasks/batch.html">Batch mode</a></p>
+
 		<p class="p"><a class="xref" href="tasks/configure_mat.html">Memory Analyzer Configuration</a></p>
 
 	</div>
diff --git a/plugins/org.eclipse.mat.ui.rcp.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.ui.rcp.tests/META-INF/MANIFEST.MF
index 23a73c5..3f01ce4 100644
--- a/plugins/org.eclipse.mat.ui.rcp.tests/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.ui.rcp.tests/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: Memory Analyzer Tests

 Bundle-SymbolicName: org.eclipse.mat.ui.rcp.tests;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-RequiredExecutionEnvironment: J2SE-1.5

 Bundle-ActivationPolicy: lazy

 Import-Package: com.ibm.icu.text;version="3.6.1",

diff --git a/plugins/org.eclipse.mat.ui.rcp.tests/pom.xml b/plugins/org.eclipse.mat.ui.rcp.tests/pom.xml
index 505212e..2c05001 100644
--- a/plugins/org.eclipse.mat.ui.rcp.tests/pom.xml
+++ b/plugins/org.eclipse.mat.ui.rcp.tests/pom.xml
@@ -8,7 +8,7 @@
 		<groupId>org.eclipse.mat</groupId>

 		<artifactId>parent</artifactId>

 		<relativePath>../../parent</relativePath>

-		<version>1.8.1-SNAPSHOT</version>

+		<version>1.9.1-SNAPSHOT</version>

 	</parent>

 

 	<artifactId>org.eclipse.mat.ui.rcp.tests</artifactId>

diff --git a/plugins/org.eclipse.mat.ui.rcp/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.ui.rcp/META-INF/MANIFEST.MF
index 89c57c2..4d49b98 100644
--- a/plugins/org.eclipse.mat.ui.rcp/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.ui.rcp/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2

 Bundle-Name: %Bundle-Name

 Bundle-SymbolicName: org.eclipse.mat.ui.rcp;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-Vendor: %Bundle-Vendor

 Require-Bundle: org.eclipse.mat.ui.help;bundle-version="1.0.0",

  org.eclipse.mat.ui;bundle-version="1.0.0",

diff --git a/plugins/org.eclipse.mat.ui.rcp/about.mappings b/plugins/org.eclipse.mat.ui.rcp/about.mappings
index dc13d4d..c10f2af 100644
--- a/plugins/org.eclipse.mat.ui.rcp/about.mappings
+++ b/plugins/org.eclipse.mat.ui.rcp/about.mappings
@@ -9,6 +9,6 @@
 #*    IBM Corporation - initial API and implementation and/or initial documentation

 #*******************************************************************************

 #Build

-0=1.8.1

+0=1.9.1

 #Product

-1=1.8.1

+1=1.9.1

diff --git a/plugins/org.eclipse.mat.ui.rcp/about.properties b/plugins/org.eclipse.mat.ui.rcp/about.properties
index 295bf34..c47a6f9 100644
--- a/plugins/org.eclipse.mat.ui.rcp/about.properties
+++ b/plugins/org.eclipse.mat.ui.rcp/about.properties
@@ -13,7 +13,7 @@
 Version: {featureVersion}\n\
 Build id: {0}\n\
 \n\
-Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others.\n\
+Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.\n\
 All rights reserved. This program and the accompanying materials\n\
 are made available under the terms of the Eclipse Public License v1.0\n\
 which accompanies this distribution, and is available at\n\
diff --git a/plugins/org.eclipse.mat.ui.rcp/plugin.properties b/plugins/org.eclipse.mat.ui.rcp/plugin.properties
index 4d763b6..04b21fb 100644
--- a/plugins/org.eclipse.mat.ui.rcp/plugin.properties
+++ b/plugins/org.eclipse.mat.ui.rcp/plugin.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2008, 2018 SAP AG.
+# Copyright (c) 2008, 2019 SAP AG.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -14,9 +14,9 @@
 activity.description.Menus_which_should_not_shown = Menus which should not be shown inside the Memory Analyzer RCP
 activity.name.Memory_Analyzer_don_t_enable = Memory Analyzer (don't enable)
 product.appName = Eclipse Memory Analyzer
-product.aboutText = Eclipse Memory Analyzer Version {1}\n\n\Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others. All rights Reserved.\n\Visit http://www.eclipse.org/mat/
+product.aboutText = Eclipse Memory Analyzer Version {1}\n\n\Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others. All rights Reserved.\n\Visit http://www.eclipse.org/mat/
 copyright=\
-Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others.\n\
+Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.\n\
 All rights reserved. This program and the accompanying materials\n\
 are made available under the terms of the Eclipse Public License v1.0\n\
 which accompanies this distribution, and is available at\n\
diff --git a/plugins/org.eclipse.mat.ui.rcp/pom.xml b/plugins/org.eclipse.mat.ui.rcp/pom.xml
index f456366..1b87439 100644
--- a/plugins/org.eclipse.mat.ui.rcp/pom.xml
+++ b/plugins/org.eclipse.mat.ui.rcp/pom.xml
Binary files differ
diff --git a/plugins/org.eclipse.mat.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.mat.ui/META-INF/MANIFEST.MF
index 49229b1..c76e0c9 100644
--- a/plugins/org.eclipse.mat.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.mat.ui/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %Bundle-Name

 Bundle-Vendor: %Bundle-Vendor

 Bundle-SymbolicName: org.eclipse.mat.ui;singleton:=true

-Bundle-Version: 1.8.1.qualifier

+Bundle-Version: 1.9.1.qualifier

 Bundle-Activator: org.eclipse.mat.ui.MemoryAnalyserPlugin

 Require-Bundle: org.eclipse.mat.api;bundle-version="1.0.0";visibility:=reexport,

  org.eclipse.core.runtime;bundle-version="3.3.100",

diff --git a/plugins/org.eclipse.mat.ui/pom.xml b/plugins/org.eclipse.mat.ui/pom.xml
index 83df722..16f2a72 100644
--- a/plugins/org.eclipse.mat.ui/pom.xml
+++ b/plugins/org.eclipse.mat.ui/pom.xml
Binary files differ
diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryBrowserProvider.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryBrowserProvider.java
index 402e742..0f564ce 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryBrowserProvider.java
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryBrowserProvider.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008, 2010 SAP AG.

+ * Copyright (c) 2008, 2019 SAP AG and IBM Corporation.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -7,6 +7,7 @@
  *

  * Contributors:

  *    SAP AG - initial API and implementation

+ *    Andrew Johnson/IBM Corporation - allow matching of subject classes by subclasses

  *******************************************************************************/

 package org.eclipse.mat.ui.internal.browser;

 

@@ -60,6 +61,11 @@
             {

                 try

                 {

+                    /*

+                     * Until we can efficiently match objects for a query against the subject we don't

+                     * need to check subclasses as if the class is present then all the subclasses

+                     * will be available too as we are considering the entire snapshot.

+                     */

                     Collection<IClass> ss = snapshot.getClassesByName(cn, false);

                     if (ss == null || ss.isEmpty())

                         continue;

diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryRegistryProvider.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryRegistryProvider.java
index 0fe8511..0dc919e 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryRegistryProvider.java
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryRegistryProvider.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008, 2010 SAP AG and others.

+ * Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -7,6 +7,7 @@
  *

  * Contributors:

  *    SAP AG - initial API and implementation

+ *    Andrew Johnson (IBM Corporation) - bug fixes

  *******************************************************************************/

 package org.eclipse.mat.ui.internal.browser;

 

@@ -23,8 +24,10 @@
 import org.eclipse.mat.ui.MemoryAnalyserPlugin;

 import org.eclipse.mat.ui.Messages;

 import org.eclipse.mat.ui.QueryExecution;

+import org.eclipse.mat.ui.editor.AbstractEditorPane;

 import org.eclipse.mat.ui.editor.MultiPaneEditor;

 import org.eclipse.mat.ui.util.IPolicy;

+import org.eclipse.mat.ui.util.PaneState;

 

 public class QueryRegistryProvider extends QueryBrowserProvider

 {

@@ -79,7 +82,9 @@
                 ArgumentSet set = query.createNewArgumentSet(editor.getQueryContext());

                 ISnapshot snapshot = (ISnapshot) editor.getQueryContext().get(ISnapshot.class, null);

                 policy.fillInObjectArguments(snapshot, query, set);

-                QueryExecution.execute(editor, editor.getActiveEditor().getPaneState(), null, set, !query.isShallow(),

+                AbstractEditorPane active = editor.getActiveEditor();

+                PaneState ps = active != null ? active.getPaneState() : null;

+                QueryExecution.execute(editor, ps, null, set, !query.isShallow(),

                                 false);

             }

             else

diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/query/arguments/ArgumentsTable.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/query/arguments/ArgumentsTable.java
index 40b1c6e..c82776b 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/query/arguments/ArgumentsTable.java
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/query/arguments/ArgumentsTable.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2008, 2018 SAP AG, IBM Corporation and others.

+ * Copyright (c) 2008, 2019 SAP AG, IBM Corporation and others.

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

  * which accompanies this distribution, and is available at

@@ -30,6 +30,7 @@
 import org.eclipse.jface.window.DefaultToolTip;

 import org.eclipse.jface.window.ToolTip;

 import org.eclipse.mat.SnapshotException;

+import org.eclipse.mat.internal.snapshot.ArgumentParser;

 import org.eclipse.mat.internal.snapshot.HeapObjectContextArgument;

 import org.eclipse.mat.internal.snapshot.HeapObjectParamArgument;

 import org.eclipse.mat.query.IContextObject;

@@ -251,7 +252,32 @@
             }

             else if (isHeapObject)

             {

-                addHeapObjectTableItems(descriptor, (HeapObjectParamArgument) argumentValue);

+                Object value = argumentValue;

+                if (value == null)

+                {

+                    // Experimental

+                    // No heap object provided, so see if query has a default heap object argument

+                    value = descriptor.getDefaultValue();

+                    if (value instanceof IHeapObjectArgument)

+                    {

+                        // The default heap object argument has a null snapshot,

+                        ISnapshot snapshot = (ISnapshot) context.get(ISnapshot.class, null);

+                        // So convert it to a string then reparse in this context.

+                        // Only really makes sense for class name or OQL arguments as object 

+                        // addresses won't apply between snapshots (except boot classloader @0x0 ?)

+                        String line = ((IHeapObjectArgument) value).getLabel();

+                        try

+                        {

+                            HeapObjectParamArgument hoa = ArgumentParser.consumeHeapObjects(snapshot, line);

+                            value = hoa;

+                        }

+                        catch (SnapshotException e)

+                        {

+                            value = null;

+                        }

+                    }

+                }

+                addHeapObjectTableItems(descriptor, (HeapObjectParamArgument) value);

             }

             else

             {

diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/oql/contentAssist/AttributeExtractor.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/oql/contentAssist/AttributeExtractor.java
index 8deeb46..e2b6648 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/oql/contentAssist/AttributeExtractor.java
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/oql/contentAssist/AttributeExtractor.java
@@ -43,9 +43,9 @@
                     readChar = doc.getChar(pos);

                     pos--;

                 }

-                while (pos >= 0 && readChar != ' ' && readChar != '@' && readChar != '.' && readChar != '\n');

+                while (pos >= 0 && readChar != ' ' && readChar != '@' && readChar != '.' && readChar != '\n' && readChar != '\r');

 

-                if (readChar == ' ' || readChar == '\n' || readChar == '.')

+                if (readChar == ' ' || readChar == '\n' || readChar == '\r' ||readChar == '.')

                     pos++;

                 return doc.get(pos + 1, currentPosition - 1 - pos);

 

diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/oql/contentAssist/OQLScanner.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/oql/contentAssist/OQLScanner.java
index 765af02..0903804 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/oql/contentAssist/OQLScanner.java
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/oql/contentAssist/OQLScanner.java
@@ -41,7 +41,7 @@
 

             public boolean isWordPart(char arg0)

             {

-                return arg0 != ' ' && arg0 != '\n';

+                return arg0 != ' ' && arg0 != '\n' && arg0 != '\r';

             }

 

             public boolean isWordStart(char arg0)

@@ -69,7 +69,7 @@
 

             public boolean isWordPart(char arg0)

             {

-                return arg0 != ' ' && arg0 != '\n' && arg0 != ')' && arg0 != '!' && arg0 != '=';

+                return arg0 != ' ' && arg0 != '\n' && arg0 != '\r' && arg0 != ')' && arg0 != '!' && arg0 != '=';

             }

 

             public boolean isWordStart(char arg0)

@@ -88,7 +88,7 @@
 

             public boolean isWordPart(char arg0)

             {

-                return arg0 != ' ' && arg0 != '\n' && arg0 != '(';

+                return arg0 != ' ' && arg0 != '\n' && arg0 != '\r' && arg0 != '(';

             }

 

             public boolean isWordStart(char arg0)

@@ -111,7 +111,7 @@
 

             public boolean isWordPart(char arg0)

             {

-                return arg0 != ' ' && arg0 != '\n' && arg0 != '(';

+                return arg0 != ' ' && arg0 != '\n' && arg0 != '\r' && arg0 != '(';

             }

 

             public boolean isWordStart(char arg0)

@@ -126,6 +126,7 @@
         wr4.addWord("outbounds", tKeyWord); //$NON-NLS-1$

         wr4.addWord("inbounds", tKeyWord); //$NON-NLS-1$

         wr4.addWord("classof", tKeyWord); //$NON-NLS-1$

+        wr4.addWord("eval", tKeyWord); //$NON-NLS-1$

 

         r[3] = wr4;