/*
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.visualvm.jmx.impl;
import com.sun.tools.visualvm.application.jvm.HeapHistogram;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
/**
*
* @author Tomas Hurka
*/
class HeapHistogramImpl extends HeapHistogram {
private static final String BOOLEAN_TEXT = "boolean"; // NOI18N
private static final String CHAR_TEXT = "char"; // NOI18N
private static final String BYTE_TEXT = "byte"; // NOI18N
private static final String SHORT_TEXT = "short"; // NOI18N
private static final String INT_TEXT = "int"; // NOI18N
private static final String LONG_TEXT = "long"; // NOI18N
private static final String FLOAT_TEXT = "float"; // NOI18N
private static final String DOUBLE_TEXT = "double"; // NOI18N
private static final String VOID_TEXT = "void"; // NOI18N
private static final char BOOLEAN_CODE = 'Z'; // NOI18N
private static final char CHAR_CODE = 'C'; // NOI18N
private static final char BYTE_CODE = 'B'; // NOI18N
private static final char SHORT_CODE = 'S'; // NOI18N
private static final char INT_CODE = 'I'; // NOI18N
private static final char LONG_CODE = 'J'; // NOI18N
private static final char FLOAT_CODE = 'F'; // NOI18N
private static final char DOUBLE_CODE = 'D'; // NOI18N
private static final char OBJECT_CODE = 'L'; // NOI18N
Set<ClassInfo> classes;
Date time;
long totalBytes;
long totalInstances;
long totalHeapBytes;
long totalHeapInstances;
HeapHistogramImpl() {
}
HeapHistogramImpl(String histogramText) {
Map<String,ClassInfoImpl> classesMap = new HashMap(1024);
Map<String,ClassInfoImpl> permGenMap = new HashMap(1024);
time = new Date();
Scanner sc = new Scanner(histogramText);
sc.useRadix(10);
sc.nextLine();
sc.nextLine();
sc.skip("-+");
sc.nextLine();
while(sc.hasNext("[0-9]+:")) { // NOI18N
ClassInfoImpl newClInfo = new ClassInfoImpl(sc);
storeClassInfo(newClInfo, classesMap);
totalHeapBytes += newClInfo.getBytes();
totalHeapInstances += newClInfo.getInstancesCount();
}
sc.next("Total"); // NOI18N
totalInstances = sc.nextLong();
totalBytes = sc.nextLong();
classes = new HashSet(classesMap.values());
}
void storeClassInfo(final ClassInfoImpl newClInfo, final Map<String, ClassInfoImpl> map) {
ClassInfoImpl oldClInfo = map.get(newClInfo.getName());
if (oldClInfo == null) {
map.put(newClInfo.getName(),newClInfo);
} else {
oldClInfo.bytes += newClInfo.getBytes();
oldClInfo.instances += newClInfo.getInstancesCount();
}
}
public Date getTime() {
return (Date) time.clone();
}
public Set<ClassInfo> getHeapHistogram() {
return classes;
}
public long getTotalInstances() {
return totalInstances;
}
public long getTotalBytes() {
return totalBytes;
}
public long getTotalHeapInstances() {
return totalHeapInstances;
}
public long getTotalHeapBytes() {
return totalHeapBytes;
}
public Set<ClassInfo> getPermGenHistogram() {
return Collections.EMPTY_SET;
}
public long getTotalPerGenInstances() {
return -1;
}
public long getTotalPermGenHeapBytes() {
return -1;
}
static class ClassInfoImpl extends ClassInfo {
long instances;
long bytes;
String name;
ClassInfoImpl(Scanner sc) {
String jvmName;
sc.next();
instances = sc.nextLong();
bytes = sc.nextLong();
jvmName = sc.next();
name = convertJVMName(jvmName);
}
public String getName() {
return name;
}
public long getInstancesCount() {
return instances;
}
public long getBytes() {
return bytes;
}
public int hashCode() {
return getName().hashCode();
}
public boolean equals(Object obj) {
if (obj instanceof ClassInfoImpl) {
return getName().equals(((ClassInfoImpl)obj).getName());
}
return false;
}
private String convertJVMName(String jvmName) {
String className = null;
int index = jvmName.lastIndexOf('['); // NOI18N
if (index != -1) {
switch(jvmName.charAt(index+1)) {
case BOOLEAN_CODE:
className=BOOLEAN_TEXT;
break;
case CHAR_CODE:
className=CHAR_TEXT;
break;
case BYTE_CODE:
className=BYTE_TEXT;
break;
case SHORT_CODE:
className=SHORT_TEXT;
break;
case INT_CODE:
className=INT_TEXT;
break;
case LONG_CODE:
className=LONG_TEXT;
break;
case FLOAT_CODE:
className=FLOAT_TEXT;
break;
case DOUBLE_CODE:
className=DOUBLE_TEXT;
break;
case OBJECT_CODE:
className=jvmName.substring(index+2,jvmName.length()-1);
break;
default:
System.err.println("Uknown name "+jvmName); // NOI18N
className = jvmName;
}
for (int i=0;i<=index;i++) {
className+="[]";
}
}
if (className == null) {
className = jvmName;
}
return className.intern();
}
}
}