Red de conocimiento informático - Material del sitio web - Cómo comprobar el tamaño de la memoria ocupada por los objetos java

Cómo comprobar el tamaño de la memoria ocupada por los objetos java

(1) Al realizar algo de almacenamiento en caché, nos resulta imposible almacenar en caché todos los datos de la base de datos en la memoria. Deberíamos estimar el tamaño del caché.

(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

*/

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) {

//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;

}

}

}

}

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

(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.