Skip to content

Instantly share code, notes, and snippets.

@laszlocsontos
Created May 12, 2014 11:00
Show Gist options
  • Save laszlocsontos/0d581d7056f655e9779f to your computer and use it in GitHub Desktop.
Save laszlocsontos/0d581d7056f655e9779f to your computer and use it in GitHub Desktop.
Demonstrates heap allocation problem caused by reusing the internal char[] arrays (value) when String.substring() is called
import com.sun.management.HotSpotDiagnosticMXBean;
import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
/**
* Demonstrates heap allocation problem with String.substring()
* http://mail.openjdk.java.net/pipermail/core-libs-dev/2012-May/010257.html
*
* The idea of taking heap dump programmatically is based on
* https://blogs.oracle.com/sundararajan/entry/programmatically_dumping_heap_from_java
*
* @author lcsontos
*
*/
public class StringTest {
// This is the name of the HotSpot Diagnostic MBean
private static final String HOTSPOT_BEAN_NAME =
"com.sun.management:type=HotSpotDiagnostic";
// field to store the hotspot diagnostic MBean
private static volatile HotSpotDiagnosticMXBean hotspotMBean;
static void dumpHeap(String fileName, boolean live) {
// initialize hotspot diagnostic MBean
initHotspotMBean();
try {
hotspotMBean.dumpHeap(fileName, live);
} catch (RuntimeException re) {
throw re;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
// initialize the hotspot diagnostic MBean field
private static void initHotspotMBean() {
if (hotspotMBean == null) {
synchronized (StringTest.class) {
if (hotspotMBean == null) {
hotspotMBean = getHotspotMBean();
}
}
}
}
// get the hotspot diagnostic MBean from the
// platform MBean server
private static HotSpotDiagnosticMXBean getHotspotMBean() {
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
HotSpotDiagnosticMXBean bean =
ManagementFactory.newPlatformMXBeanProxy(server,
HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);
return bean;
} catch (RuntimeException re) {
throw re;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
public static void main(String[] args) {
final int len = 1 * 1024 * 1024;
char[] value = new char[len];
for (int i = 0; i < len; i++) {
value[i] = (char)('A' + (i % 26));
}
String test = new String(value);
test = test.substring(len - 10, len);
System.out.println("test=" + test);
final String fileName = "/tmp/" + System.currentTimeMillis() + ".hprof";
dumpHeap(fileName, true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment