Bug 298810 - Provide ability to search for number of instances
diff --git a/org.eclipse.jdt.debug.tests/testprograms/java6/AllInstancesTests.java b/org.eclipse.jdt.debug.tests/testprograms/java6/AllInstancesTests.java
new file mode 100644
index 0000000..c954eb3
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/testprograms/java6/AllInstancesTests.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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 java6;
+
+import java.util.ArrayList;
+
+/**
+ * Class to test instance retrieval features
+ */
+public class AllInstancesTests {
+
+	class RefObject {
+		private int fNum = -1;
+		
+		public RefObject(int number) {
+			fNum = number;
+		}
+		public String toString() {
+			return "RefObject"+fNum;
+		}
+	}
+	
+	class RefClass {
+		public ArrayList makeReferences(int number) {
+			ArrayList list = new ArrayList(number);
+			for(int i = 0; i < number; i++) {
+				list.add(new RefObject(i));
+			}
+			return list;
+		}
+	}
+	
+	public ArrayList makeRefObjectReferences(int number) {
+		ArrayList list = new ArrayList(number);
+		for(int i = 0; i < number; i++) {
+			list.add(new RefObject(i));
+		}
+		return list;
+	}
+	
+	public ArrayList makeRefClassReferences(int number) {
+		ArrayList list = new ArrayList(number);
+		for(int i = 0; i < number; i++) {
+			list.add(new RefClass());
+		}
+		return list;
+	}
+	
+	public static void main(String[] args) {
+		AllInstancesTests ait = new AllInstancesTests();
+		ArrayList list = ait.makeRefObjectReferences(12);
+		RefObject ro = ait.new RefObject(-1);
+		list = ait.makeRefClassReferences(1001);
+		RefClass rc = ait.new RefClass();
+		System.out.println("end");  //TODO breakpoint
+	}
+}
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
index b1e5b50..42bc2c5 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 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
@@ -101,6 +101,7 @@
 import org.eclipse.jdt.debug.tests.state.RefreshStateTests;
 import org.eclipse.jdt.debug.tests.ui.DetailPaneManagerTests;
 import org.eclipse.jdt.debug.tests.ui.ViewMangementTests;
+import org.eclipse.jdt.debug.tests.variables.TestInstanceRetrieval;
 import org.eclipse.jdt.debug.tests.variables.TestLogicalStructures;
 
 /**
@@ -180,6 +181,7 @@
 		addTest(new TestSuite(StaticVariableTests.class));
 		addTest(new TestSuite(ArrayTests.class));
 		addTest(new TestSuite(TestLogicalStructures.class));
+		addTest(new TestSuite(TestInstanceRetrieval.class));
 		
 	//Stepping tests
 		addTest(new TestSuite(StepFilterTests.class));
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java
index 367c91c..b3a4bcf 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/ProjectCreationDecorator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 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
@@ -219,6 +219,9 @@
         
         //launch configuration manager tests
         createLaunchConfiguration("RunnableAppletImpl");
+        
+        // instance retrieval tests
+        createLaunchConfiguration("java6.AllInstancesTests");
     }
 
     /**
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/TestInstanceRetrieval.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/TestInstanceRetrieval.java
new file mode 100644
index 0000000..d494d61
--- /dev/null
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/TestInstanceRetrieval.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.jdt.debug.tests.variables;
+
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
+import org.eclipse.jdt.debug.core.IJavaObject;
+import org.eclipse.jdt.debug.core.IJavaReferenceType;
+import org.eclipse.jdt.debug.core.IJavaStackFrame;
+import org.eclipse.jdt.debug.core.IJavaThread;
+import org.eclipse.jdt.debug.core.IJavaVariable;
+import org.eclipse.jdt.debug.tests.AbstractDebugTest;
+
+/**
+ * Tests for instance retrieval
+ */
+public class TestInstanceRetrieval extends AbstractDebugTest {
+
+	/**
+	 * Constructs test.
+	 * 
+	 * @param name test name
+	 */
+	public TestInstanceRetrieval(String name) {
+		super(name);
+	}
+	
+	/**
+	 * Test the logical structure for a list.
+	 * 
+	 * @throws Exception
+	 */
+	public void testGetInstances() throws Exception {
+		String typeName = "java6.AllInstancesTests";
+		createLineBreakpoint(61, typeName);
+		IJavaLineBreakpoint bp2 = createLineBreakpoint(63, typeName);
+		IJavaThread thread= null;
+		try {
+			thread= launchToBreakpoint(typeName);
+			IJavaDebugTarget target = (IJavaDebugTarget) thread.getDebugTarget();
+			if (target.supportsInstanceRetrieval()) {
+				assertNotNull("Breakpoint not hit within timeout period", thread);
+				
+				IBreakpoint hit = getBreakpoint(thread);
+				assertNotNull("suspended, but not by breakpoint", hit);
+	
+				IJavaStackFrame frame = (IJavaStackFrame) thread.getTopStackFrame();
+				assertNotNull("missing top frame", frame);
+				
+				IJavaVariable variable = frame.findVariable("ro");
+				assertNotNull("Missing variable 'ro'", variable);
+				
+				IJavaObject object = (IJavaObject) variable.getValue();
+				IJavaReferenceType refType = (IJavaReferenceType) object.getJavaType();
+				long instanceCount = refType.getInstanceCount();
+				IJavaObject[] instances = refType.getInstances(100);
+				
+				assertEquals("Wrong instance count", 13, instanceCount);
+				assertEquals("Wrong number of instances", 13, instances.length);
+				for (int i = 0; i < instances.length; i++) {
+					assertEquals("Instance is of unexpected type", refType, instances[i].getJavaType());
+				}
+				
+				thread = resumeToLineBreakpoint(thread, bp2);
+				frame = (IJavaStackFrame) thread.getTopStackFrame();
+				assertNotNull("missing top frame", frame);
+				
+				variable = frame.findVariable("rc");
+				assertNotNull("Missing variable 'rc'", variable);
+				
+				object = (IJavaObject) variable.getValue();
+				refType = (IJavaReferenceType) object.getJavaType();
+				instanceCount = refType.getInstanceCount();
+				instances = refType.getInstances(100);
+				
+				assertEquals("Wrong instance count", 1002, instanceCount);
+				assertEquals("Wrong number of instances", 100, instances.length);
+				for (int i = 0; i < instances.length; i++) {
+					assertEquals("Instance is of unexpected type", refType, instances[i].getJavaType());
+				}
+			}
+		} finally {
+			terminateAndRemove(thread);
+			removeAllBreakpoints();
+		}				
+	}	
+
+}
diff --git a/org.eclipse.jdt.debug.ui/plugin.properties b/org.eclipse.jdt.debug.ui/plugin.properties
index 89a5d98..8f67ed1 100644
--- a/org.eclipse.jdt.debug.ui/plugin.properties
+++ b/org.eclipse.jdt.debug.ui/plugin.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2009 IBM Corporation and others.
+# Copyright (c) 2000, 2010 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
@@ -215,7 +215,9 @@
 ActionDefinition.allReferences.name=All References
 ActionDefinition.allReferences.description=Inspect all references to the selected object
 ActionDefinition.allInstances.name=All Instances
-ActionDefinition.allInstances.description=View all instances of the selected object loaded in the target VM
+ActionDefinition.allInstances.description=View all instances of the selected type loaded in the target VM
+ActionDefinition.instanceCount.name=Instance Count
+ActionDefinition.instanceCount.description=View the instance count of the selected type loaded in the target VM
 ActionDefinition.breakpointproperties.name=Breakpoint P&roperties
 ActionDefinition.breakpointproperties.description=View and edit the properties for a given Java breakpoint
 CommandDefinition.breakpointproperties.name=Java Breakpoint Properties
@@ -270,7 +272,10 @@
 EditLogicalStructure.label=Edit Logical Structure...
 
 allInstances.label=All Ins&tances...
-allInstances.tooltip=Displays a popup window showing all live instances of the selected java type in the current running VM
+allInstances.tooltip=Displays a popup window showing all live instances of the selected type in the current running VM
+
+instanceCount.label=Instance Co&unt...
+instanceCount.tooltip=Displays the number of live instances of the selected type in the current running VM
 
 allReferences.label=All &References...
 allReferences.tooltip=Inspect references to the selected object
diff --git a/org.eclipse.jdt.debug.ui/plugin.xml b/org.eclipse.jdt.debug.ui/plugin.xml
index 33fb29a..d01f881 100644
--- a/org.eclipse.jdt.debug.ui/plugin.xml
+++ b/org.eclipse.jdt.debug.ui/plugin.xml
Binary files differ
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java
index b491e90..50e3bdd 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 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
@@ -367,4 +367,6 @@
 	public static String JavaPrimitivesPreferencePage_1;
 	
 	public static String JavaStepFilterPreferencePage__Use_step_filters;
+
+	public static String JavaVariableLabelProvider_0;
 }
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties
index 0a1c572..ddd5576 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2008 IBM Corporation and others.
+# Copyright (c) 2000, 2010 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
@@ -295,6 +295,7 @@
 JavaDebugPreferencePage_26=Access
 JavaDebugPreferencePage_27=Modification
 JavaDebugPreferencePage_0=See <a>''{0}''</a> for general debug settings.
+JavaVariableLabelProvider_0=unavailable
 EditLogicalStructureDialog_0=Qualified type &name:
 EditLogicalStructureDialog_1=&Browse...
 EditLogicalStructureDialog_2=D&escription:
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/AllInstancesActionDelegate.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/AllInstancesActionDelegate.java
index 59eb5a1..523786e 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/AllInstancesActionDelegate.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/AllInstancesActionDelegate.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * Copyright (c) 2006, 2010 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
@@ -98,7 +98,7 @@
 						    		IJavaElement[] selectedTypes = ((ICodeAssist)element).codeSelect(selectedWord.getOffset(), selectedWord.getLength());
 						    		// findWord() will only return one element, so only check the first element
 						    		if (selectedTypes.length > 0){
-						    			runAllInstancesForType(selectedTypes[0]);  
+						    			runForSelection(selectedTypes[0]);  
 						    			return;
 						    		}
 								} catch (JavaModelException e){
@@ -111,7 +111,7 @@
 					
 				// Otherwise, get the first selected element and check if it is a type
 				} else if (selection instanceof IStructuredSelection){
-					runAllInstancesForType(((IStructuredSelection)selection).getFirstElement());
+					runForSelection(((IStructuredSelection)selection).getFirstElement());
 					return;
 				}
 			}
@@ -120,12 +120,12 @@
 	}
 	
 	/**
-	 * Checks if the passed element is a java type or constructor that all instances can 
-	 * be retrieved for. If so, retrieves the instances and displays them in a popup dialog.
+	 * Resolves a debug reference type for the selected element and then
+	 * runs the action.
 	 * 
-	 * @param selectedElement The element to obtain all instances for
+	 * @param selectedElement a method, type, or variable
 	 */
-	protected void runAllInstancesForType(Object selectedElement){
+	protected void runForSelection(Object selectedElement){
 		if (selectedElement != null){
 						
 			IJavaType type = null;
@@ -147,13 +147,8 @@
 							if(types != null && types.length > 0) {
 								type = types[0];
 							} else {
-								// If the type is not known the the VM, open a popup dialog with 0 instances
-								JDIAllInstancesValue aiv = new JDIAllInstancesValue((JDIDebugTarget)target, null);
-								InspectPopupDialog ipd = new InspectPopupDialog(getShell(), 
-										getAnchor(), 
-										PopupInspectAction.ACTION_DEFININITION_ID,
-										new JavaInspectExpression(MessageFormat.format(Messages.AllInstancesActionDelegate_2, new String[]{itype.getElementName()}), aiv));
-								ipd.open();
+								// If the type is not known the the VM, open a pop-up dialog with 0 instances
+								displayNoInstances(target, itype.getFullyQualifiedName());
 								return;
 							}
 						}
@@ -179,23 +174,48 @@
 					
 			if(type instanceof JDIReferenceType) {
 				JDIReferenceType rtype = (JDIReferenceType) type;
-				try{
-					JDIAllInstancesValue aiv = new JDIAllInstancesValue((JDIDebugTarget)rtype.getDebugTarget(), rtype);
-					InspectPopupDialog ipd = new InspectPopupDialog(getShell(), 
-							getAnchor(), 
-							PopupInspectAction.ACTION_DEFININITION_ID,
-							new JavaInspectExpression(MessageFormat.format(Messages.AllInstancesActionDelegate_2, new String[]{type.getName()}), aiv));
-					ipd.open();
-					return;
-				} catch (DebugException e) {
-					JDIDebugUIPlugin.log(e);
-					report(Messages.AllInstancesActionDelegate_0,getPart());
-				}
+				displayInstaces((JDIDebugTarget)rtype.getDebugTarget(), rtype);
+				return;
 			}
 		}
 		report(Messages.AllInstancesActionDelegate_3,getPart());
 	}
 	
+	/**
+	 * No types are loaded in the given target with the specified type name. Displays the result.
+	 * 
+	 * @param target target
+	 * @param typeName resolve type name
+	 */
+	protected void displayNoInstances(IJavaDebugTarget target, String typeName) {
+		JDIAllInstancesValue aiv = new JDIAllInstancesValue((JDIDebugTarget)target, null);
+		InspectPopupDialog ipd = new InspectPopupDialog(getShell(), 
+				getAnchor(), 
+				PopupInspectAction.ACTION_DEFININITION_ID,
+				new JavaInspectExpression(MessageFormat.format(Messages.AllInstancesActionDelegate_2, new String[]{typeName}), aiv));
+		ipd.open();
+	}
+	
+	/**
+	 * Display instances of the given resolved type.
+	 * 
+	 * @param target target
+	 * @param rtype resolved reference type
+	 */
+	protected void displayInstaces(IJavaDebugTarget target, JDIReferenceType rtype) {
+		try{
+			JDIAllInstancesValue aiv = new JDIAllInstancesValue((JDIDebugTarget)rtype.getDebugTarget(), rtype);
+			InspectPopupDialog ipd = new InspectPopupDialog(getShell(), 
+					getAnchor(), 
+					PopupInspectAction.ACTION_DEFININITION_ID,
+					new JavaInspectExpression(MessageFormat.format(Messages.AllInstancesActionDelegate_2, new String[]{rtype.getName()}), aiv));
+			ipd.open();
+		} catch (DebugException e) {
+			JDIDebugUIPlugin.log(e);
+			report(Messages.AllInstancesActionDelegate_0,getPart());
+		}
+	}
+	
 	 /**
      * Convenience method for printing messages to the status line
      * @param message the message to be displayed
@@ -324,7 +344,7 @@
 	/**
 	 * @return the shell to use for new popups or <code>null</code>
 	 */
-	private Shell getShell(){
+	protected Shell getShell(){
 		if (fWindow != null){
 			return fWindow.getShell();
 		}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/InstanceCountActionDelegate.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/InstanceCountActionDelegate.java
new file mode 100644
index 0000000..02be5d1
--- /dev/null
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/InstanceCountActionDelegate.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.jdt.internal.debug.ui.heapwalking;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.debug.core.IJavaDebugTarget;
+import org.eclipse.jdt.internal.debug.core.model.JDIReferenceType;
+import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
+import org.eclipse.jface.dialogs.MessageDialog;
+
+import com.ibm.icu.text.MessageFormat;
+
+/**
+ * Action to display the instance count for a selected type.
+ * 
+ * @since 3.6
+ */
+public class InstanceCountActionDelegate extends AllInstancesActionDelegate {
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.debug.ui.heapwalking.AllInstancesActionDelegate#displayInstaces(org.eclipse.jdt.debug.core.IJavaDebugTarget, org.eclipse.jdt.internal.debug.core.model.JDIReferenceType)
+	 */
+	protected void displayInstaces(IJavaDebugTarget target, JDIReferenceType rtype) {
+		try {
+			displayNumInstances(rtype.getName(), rtype.getInstanceCount());
+		} catch (CoreException e) {
+			JDIDebugUIPlugin.log(e);
+			report(Messages.AllInstancesActionDelegate_0,getPart());
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.debug.ui.heapwalking.AllInstancesActionDelegate#displayNoInstances(org.eclipse.jdt.debug.core.IJavaDebugTarget, java.lang.String)
+	 */
+	protected void displayNoInstances(IJavaDebugTarget target, String typeName) {
+		displayNumInstances(typeName, 0);
+	}
+	
+	/**
+	 * Displays a message dialog with the number of instances.
+	 * 
+	 * @param typeName type name
+	 * @param instanceCount number of instances
+	 */
+	protected void displayNumInstances(String typeName, long instanceCount) {
+		String message = null;
+		if (instanceCount == 0L) {
+			message = MessageFormat.format(Messages.InstanceCountActionDelegate_0, new String[]{typeName});
+		} else if (instanceCount == 1L) {
+			message = MessageFormat.format(Messages.InstanceCountActionDelegate_1, new String[]{typeName});
+		} else {
+			message = MessageFormat.format(Messages.InstanceCountActionDelegate_2, new String[]{Long.toString(instanceCount), typeName});
+		}
+		MessageDialog.openInformation(getShell(), Messages.InstanceCountActionDelegate_3, message);
+	}
+}
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/Messages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/Messages.java
index bde2f71..fa5f51a 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/Messages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/Messages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2006, 2009 IBM Corporation and others.
+ *  Copyright (c) 2006, 2010 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
@@ -28,6 +28,14 @@
 	public static String AllReferencesInViewActionDelegate_0;
 	public static String AllReferencesInViewActionDelegate_1;
 
+	public static String InstanceCountActionDelegate_0;
+
+	public static String InstanceCountActionDelegate_1;
+
+	public static String InstanceCountActionDelegate_2;
+
+	public static String InstanceCountActionDelegate_3;
+
 	static {
 		// initialize resource bundle
 		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/Messages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/Messages.properties
index bb60951..52b95a0 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/Messages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/heapwalking/Messages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-#  Copyright (c) 2006, 2009 IBM Corporation and others.
+#  Copyright (c) 2006, 2010 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
@@ -15,3 +15,7 @@
 AllReferencesActionDelegate_1={0} referenced from:
 AllReferencesInViewActionDelegate_0=Operation Not Supported
 AllReferencesInViewActionDelegate_1=The current VM does not support reference retrieval.  References will not be shown in the view.
+InstanceCountActionDelegate_0=There are no instances of {0}
+InstanceCountActionDelegate_1=There is 1 instance of {0}
+InstanceCountActionDelegate_2=There are {0} instances of {1}
+InstanceCountActionDelegate_3=Instance Count
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableColumnPresentation.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableColumnPresentation.java
index b6e9fea..ba44c41 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableColumnPresentation.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableColumnPresentation.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006 IBM Corporation and others.
+ * Copyright (c) 2006, 2010 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
@@ -23,11 +23,16 @@
 	 */
 	public final static String JAVA_VARIABLE_COLUMN_PRESENTATION = IJavaDebugUIConstants.PLUGIN_ID + ".VARIALBE_COLUMN_PRESENTATION";  //$NON-NLS-1$
 	/**
-	 * Default column identifiers
+	 * Instance ID column identifier
 	 */
 	public final static String COLUMN_INSTANCE_ID = JAVA_VARIABLE_COLUMN_PRESENTATION + ".COL_INSTANCE_ID"; //$NON-NLS-1$
 	
 	/**
+	 * Instance count column identifier
+	 */
+	public final static String COLUMN_INSTANCE_COUNT = JAVA_VARIABLE_COLUMN_PRESENTATION + ".COL_INSTANCE_COUNT"; //$NON-NLS-1$
+	
+	/**
 	 * Column ids
 	 */
 	private static String[] fgAllColumns = null;
@@ -38,9 +43,10 @@
 	public String[] getAvailableColumns() {
 		if (fgAllColumns == null) {
 			String[] basic = super.getAvailableColumns();
-			fgAllColumns = new String[basic.length + 1];
+			fgAllColumns = new String[basic.length + 2];
 			System.arraycopy(basic, 0, fgAllColumns, 0, basic.length);
 			fgAllColumns[basic.length] = COLUMN_INSTANCE_ID;
+			fgAllColumns[basic.length+1] = COLUMN_INSTANCE_COUNT;
 		}
 		return fgAllColumns;
 	}
@@ -52,6 +58,9 @@
 		if (COLUMN_INSTANCE_ID.equals(id)) {
 			return VariableMessages.JavaVariableColumnPresentation_0;
 		}
+		if (COLUMN_INSTANCE_COUNT.equals(id)) {
+			return VariableMessages.JavaVariableColumnPresentation_1;
+		}
 		return super.getHeader(id);
 	}
 	
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableLabelProvider.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableLabelProvider.java
index 280daac..42cc206 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableLabelProvider.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/JavaVariableLabelProvider.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2009 IBM Corporation and others.
+ * Copyright (c) 2008, 2010 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
@@ -26,7 +26,11 @@
 import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
 import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
 import org.eclipse.debug.ui.IDebugModelPresentation;
+import org.eclipse.jdt.debug.core.IJavaInterfaceType;
+import org.eclipse.jdt.debug.core.IJavaObject;
+import org.eclipse.jdt.debug.core.IJavaReferenceType;
 import org.eclipse.jdt.debug.core.IJavaStackFrame;
+import org.eclipse.jdt.debug.core.IJavaType;
 import org.eclipse.jdt.debug.core.IJavaValue;
 import org.eclipse.jdt.debug.core.IJavaVariable;
 import org.eclipse.jdt.debug.core.JDIDebugModel;
@@ -133,6 +137,26 @@
 			}
 			return ""; //$NON-NLS-1$
 		}
+		if (JavaVariableColumnPresentation.COLUMN_INSTANCE_COUNT.equals(columnId)) {
+			if (value instanceof IJavaObject) {
+				IJavaType jType = ((IJavaObject)value).getJavaType();
+				if (jType == null && variable instanceof IJavaVariable) {
+					jType = ((IJavaVariable)variable).getJavaType();
+				}
+				if (jType instanceof IJavaReferenceType) {
+					if (!(jType instanceof IJavaInterfaceType)) {
+						long count = ((IJavaReferenceType)jType).getInstanceCount();
+						if (count == -1) {
+							return DebugUIMessages.JavaVariableLabelProvider_0;
+						}
+						StringBuffer buffer = new StringBuffer();
+						buffer.append(count);
+						return buffer.toString();
+					}
+				}
+			}
+			return ""; //$NON-NLS-1$
+		}
 		return super.getColumnText(variable, value, context, columnId);
 	}
 
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/VariableMessages.java b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/VariableMessages.java
index 22921ae..1e75bdc 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/VariableMessages.java
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/VariableMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * Copyright (c) 2006, 2010 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
@@ -28,5 +28,6 @@
 	}
 
 	public static String JavaVariableColumnPresentation_0;
+	public static String JavaVariableColumnPresentation_1;
 
 }
diff --git a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/VariableMessages.properties b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/VariableMessages.properties
index 856ad3a..0f53e21 100644
--- a/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/VariableMessages.properties
+++ b/org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/variables/VariableMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2006, 2007 IBM Corporation and others.
+# Copyright (c) 2006, 2010 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
@@ -10,3 +10,4 @@
 ###############################################################################
 
 JavaVariableColumnPresentation_0=Instance ID
+JavaVariableColumnPresentation_1=Instance Count
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaReferenceType.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaReferenceType.java
index 75d80bf..efca630 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaReferenceType.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaReferenceType.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 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
@@ -151,5 +151,15 @@
      * @since 3.3
      */
     public IJavaObject[] getInstances(long max) throws DebugException;
+    
+    /**
+     * Returns the number of instances of this type currently allocated in the target
+     * virtual machine, or -1 if instance counts are not supported by the target.
+     * 
+     * @return number of instances of this type, or -1 if unsupported
+     * @throws DebugException on failure
+     * @since 3.6
+     */
+    public long getInstanceCount() throws DebugException;
 	
 }
diff --git a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIReferenceType.java b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIReferenceType.java
index 773b653..3bc4cd5 100644
--- a/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIReferenceType.java
+++ b/org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIReferenceType.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 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
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.debug.core.model;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
@@ -29,6 +30,7 @@
 import com.sun.jdi.ReferenceType;
 import com.sun.jdi.Type;
 import com.sun.jdi.Value;
+import com.sun.jdi.VirtualMachine;
 
 /**
  * References a class, interface, or array type.
@@ -292,4 +294,22 @@
 		return null;
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.debug.core.IJavaReferenceType#getInstanceCount()
+	 */
+	public long getInstanceCount() throws DebugException {
+		JDIDebugTarget target = getJavaDebugTarget();
+		if (target.supportsInstanceRetrieval()) {
+			ArrayList list = new ArrayList(2);
+			list.add(getUnderlyingType());
+			VirtualMachine vm = getVM();
+			try {
+				long[] counts = vm.instanceCounts(list);
+				return counts[0];
+			} catch (RuntimeException e) {
+				targetRequestFailed(JDIDebugModelMessages.JDIReferenceType_5, e);
+			}
+		}
+		return -1;
+	}
 }