Cómo comprobar el tamaño de la memoria ocupada por los objetos java
(2) Cuando se producen pérdidas de memoria, podemos observar el tamaño de algunos objetos para localizar el problema. Por supuesto, existen otros métodos más efectivos, como usar MAT para analizar archivos de volcado.
(3) Según la configuración de la memoria dinámica del jvm, podemos saber el número máximo de objetos que se pueden crear.
A partir de jdk5, se proporciona una API de detección. Tiene un método llamado getObjectSize(), pero este método tiene dos problemas:
(1) No se puede utilizar directamente. Debe implementar un agente instrumentado y colocarlo en un paquete jar.
(2) Solo puede devolver el tamaño de un único objeto, pero no el tamaño de los subobjetos contenidos en él.
En cuanto al primer problema, es fácil de solucionar. Declarar un método "premain" en cualquier clase convierte a esa clase en un agente:
Clase pública SizeOfAgent {
Static Instrumentation Institute;
/* *Inicializar agente* /
premain vacío estático público (argumentos del agente de cadena, inst instP){
inst = instP
}
}
El método premain() se llamará cuando se inicie jvm y la instancia del objeto de Instrumentación se pasará al mismo tiempo. Para indicarle a la JVM qué clase instrumentar el agente, debe escribir esta clase en el paquete jar.
Luego establezca algunas propiedades en el archivo manifest.mf:
premain-Class: sizeof agent .sizeof agent
Ruta de clase de inicio:
can-Redefine-class: false
Al iniciar una aplicación java, especifique el parámetro -javaagent:
Agente Java-Java: sizeofag.jar lt; su clase principal gt;
Después de obtener esta instancia de detección, puede llamar al método sizeOf():
Clase pública SizeOfAgent {
Instituto de investigación de instrumentación estática;
// ...
public static long sizeOf(Object o){
return inst . getobjectsize(o);
}
}
Luego puedes usar la reflexión para obtener el tamaño del objeto secundario.
El código completo es el siguiente:
Paquete com .bj58
Importar instrumento Java . >Importar Java .reflejar .matriz;
Importar lenguaje de Java . Java . util . mapa de hash de identidad
Clase pública SizeOfAgent .
Instituto de Investigación de Instrumentación Estática;
/**Agente de inicialización*/
premain vacío estático público (argumentos del agente de cadena, inst instP){
inst = instP
}
/**
* Devuelve el tamaño de un objeto que no tiene subobjetos miembros.
*
* @param o
*El objeto para obtener el tamaño
* @Devuelve el tamaño del objeto
*/
public static long sizeOf(Object o){
if (inst == null) {
Lanzar nueva IllegalStateException(
No se puede acceder al entorno de detección \n "
"Compruebe si el archivo jar que contiene la clase SizeOfAgent es \n "
"\"-javaagent\ " en java. ");
}
return inst. getobjectsize(o);
}
/**
* Calcula el tamaño completo del objeto cuyo gráfico de jerarquía se itera.
*
* @param obj
*El objeto cuyo tamaño se va a calcular
* @Devuelve el tamaño del objeto p>
*/
public static long fullSizeOf(Object obj){
Mapa ltObject, Objeto gtvisited = new IdentityHashMap ltObject, Objeto gt(); p>Pila ltObject gtstack = nueva pila ltObject gt();
resultado largo = internalSizeOf(obj, pila, visitado
And (!stack.isEmpty()) {
resultado = tamaño interno de(pila . pop(), pila, visitado);
}
visitado
; Resultado de retorno;
}
SkipObject booleano estático privado (Objeto obj, Mapa ltObjeto, Objeto gt visitado) {
if (obj instancia de cadena) { p>
//Omitir cadena de prácticas
if (obj == ((String) obj).Intern()){
Devuelve verdadero
}
}
return (obj == null) //Omitir el objeto visitado
| contiene clave(obj);
p>}
Privado estático largo internalSizeOf(Objeto obj, Pila ltObjeto gt pila,
Mapa ltObjeto, Objeto gt visitado){
if ( skipObject(obj, visitado)) {
Devuelve 0;
}
visited.put(obj, null);
Largo result = 0;
//Obtiene el tamaño del puntero del miembro variable original del objeto
result = sizeof agent . /Procesar todos los elementos del Array
class clazz = obj . getclass();
if (clazz.isArray()) {
if (clazz.getName( ).
longitud()! = 2) {//Omitir matriz de tipo primitivo
int length = array . getlength(obj);
for(int I = 0; I lt length; i) {< / p>
stack.add(Array.get(obj, I));
}
}
Devuelve el resultado;
}
//Procesa todos los campos del objeto
Y (clazz! = null) {
field[]fields = clazz getdeclaredfields(. ) ;
for(int I = 0; iltfields.lengthi) {
if (!Modifier.isStatic(fields[i].getModifiers())) {
if(Field[i].getType().isPrimitive()) {
Continuar; //Omitir el campo original
} De lo contrario {
campo[i]. set access(true);
Prueba {
//El objeto a evaluar se coloca en la pila
objectToAdd = campos[i].
get(obj);
if (objectToAdd!= null) {
apilar . catch(IllegalAccessException ex){
Asertar falso;
}
}
}
} p>
clazz = clazz . obtener super clase();
}
Devolver resultados;
}
}
Entonces podemos hacer una prueba:
prueba de clase pública{
personal de clase estática{
ID int privada
Nombre de cadena privada;
Dirección de cadena privada;
Carácter público (int id, nombre de cadena, dirección de cadena) {
this.id = id
this.name = nombre
this.address =address;
}
}
Vacío estático público main(String[] args) lanza una excepción {
人p = new人(12,"xujsh","bj");
long size = sizeof fullsizeof( p. );
sistema . out . println(tamaño);
}
}
Cambiar a la línea de comando:
d:\workspace\objsize\src gt;versión de Java
versión de Java "1.6.0_22"
Java(TM) SE Runtime Environment (compilación 1.6.0_22- b04)
Máquina virtual cliente Java HotSpot(TM) (compilación 17.1-b03, modo mixto, compartido)
d:\workspace\objsize\src>javac com/bj58/test /*. Lenguaje Java (un lenguaje informático, especialmente utilizado para crear sitios web)
d:\workspace\objsize\src gt;jar -cvfm size.jar manifest. MF com/bj58/test/*
Lista (manifiesto)
Agregar: com/bj58/test/sizeof agent class(read = 3119)(write = 1698)( Compresión. 45).
Agregar: com/bj58/test/sizeof agent Java (lectura = 3147) (escritura = 1204) (compresión 61).
agregar: com/bj58/test/test $ person . (lectura = 442) (escritura = 305) (comprimido 30).
Agregar: com/bj58/test/test .class(lectura = 692)(escritura = 441)(comprimido 36).
Agregar: com/bj58/test/test . Java (lectura = 509) (escritura = 290) (comprimido 43).
d:\workspace\objsize\src gt; agente Java-Java: tamaño .jar com .prueba .
24
Manifiesto. MF:
Versión de manifiesto: 1.0
Clase principal: com.bj58.test.Test
Clase preprincipal: com.bj58.test.sizeof agente
Ruta de clase de arranque:
can-Redefine-class: false
Tenga en cuenta el formato del manifiesto. Los archivos MF son estrictos, cada línea debe cumplir con los siguientes requisitos: clave: valor en blanco ingresar.
¿Cómo usarlo en aplicaciones web?
Tome mi Tomcat como ejemplo.
(1) Cargue size.jar en el directorio lib de tomcat.
(2) Modificar catalina.sh:
Agregar una línea:
Java _ opts = " $ Java _ opts-Agente Java: $ catalina _ home /lib/size .jar "//Esta línea se agregó recientemente.
if[-z "$ LOGGING_MANAGER"]; entonces
JAVA_OPTS="$JAVA_OPTS-DJ ava.util.logging.manager=org.Apache. juli . classloaderlogmanager "
Otros
JAVA _ OPTS = " $ JAVA _ OPTS $ LOGGING _ MANAGER "
El barco no corre con los gastos de carga p >
(3) Agregar un controlador en la aplicación:
@Path(value = "/api/size ")
@GET
Tamaño del resultado de la operación pública(){
Mapa ltLong, Lista ltLong gt gtmap = API utils .
tamaño largo = tamaño completo del agente
Devuelve nuevo ApiActionResult(" size: " size);
}
Luego puedes usar el navegador para acceder y hacer preguntas.