2010-06-30 14 views
7

He estado escribiendo una pequeña aplicación java (¡la primera!), Que hace solo algunas cosas en este momento. Actualmente, ejecuta la clase principal que inicia una clase gui (una clase que escribí que amplía JFrame que solo contiene un JTextArea), una clase que carga un archivo local a través de un BufferedInputStream de aproximadamente 40 kb y una clase que carga una entrada desde un Archivo de propiedades JavaUso de la memoria de la aplicación Java

Todo funciona maravillosamente, sin embargo, estaba mirando el administrador de tareas de Windows y noté algo que me pareció extraño. Cuando lance la aplicación, el uso de RAM salta a unos 40MB mientras carga el archivo local y extrae algunos valores de él para mostrar en el JTextArea, lo cual me parece normal debido a la JVM, las clases base de Java, etc. Sin embargo, cuando la aplicación ha terminado de cargar el archivo, simplemente permanece inactivo, ya que actualmente no lo tengo haciendo otra cosa. Mientras está inactivo, mientras la ventana esté activa, el uso de la memoria de la aplicación comienza a aumentar en 10-20 kb por segundo. Esto me parece extraño. Si hago clic en otro programa para hacer que este sea la ventana inactiva, la memoria aún aumenta, pero a un ritmo mucho más lento (aproximadamente 10 kb cada 3-5 segundos).

No he probado para ver qué tan lejos subiría, pero esto me parece un comportamiento muy extraño. ¿Es este comportamiento Java normal? Supongo que es posible que mi código pueda estar perdiendo memoria, pero no estoy seguro de cómo. Me aseguré de cerrar el BufferedInputStream que estoy usando, y no puedo ver qué más podría causar esto.

Lo siento si mi explicación no tiene sentido, pero agradecería cualquier información y/o consejos que pueda tener alguien.

ACTUALIZACIÓN:

A sugerencia, básicamente quitaron mi solicitud a la clase principal, que simplemente llama a la clase GUI. La clase gui solo extiende JFrame y establece el tamaño de la ventana, el funcionamiento cercano y las propiedades visibles. Con estos cambios, la memoria aún crece a 10-20 kb, pero a un ritmo más lento. Esto, en conjunción con otros consejos que he recibido me lleva a creer que esto es solo Java. Continuaré jugando con eso y les dejaré saber si descubro algo más interesante.

+0

Felicidades en su primera aplicación !!! ¿Tal vez podría publicar algún código? Sin código solo estamos adivinando. Además, simplemente siga supervisándolo para ver si realmente sigue aumentando o si simplemente se detiene en algún momento. Publica tus resultados –

+1

@Romain, gracias! Pensé en publicar mi código, pero sinceramente, estaba más interesado en ver si esto es de alguna manera un comportamiento normal de Java (¡no lo creo, pero todo es posible!). Investigaré más y luego publicaré el código si no puedo entender por qué en unos días. ¡Gracias! –

+1

#masternosaj Es normal que la memoria fluctúe un poco, ya que internamente se actualiza a la pantalla y se realiza la recolección de elementos no utilizados. No es normal que la memoria siga creciendo. Si eres un principiante de Java, he visto personas que piden revisiones de código de secciones de código en este sitio. –

Respuesta

9

Trate de monitorear el uso del montón con jconsole en lugar del administrador de tareas de Windows:

  • poner en marcha su aplicación con la opción -Dcom.sun.management.jmxremote por ejemplo,

java -Dcom.sun.management.jmxremote -jar myapp.jar

  • jconsole lanzamiento desde la línea de comandos, y conectar con el pid local del proceso de java que comenzó en el último paso.
  • Haga clic sobre la memoria y ver la pila de memoria (la pantalla por defecto)

Si ver por un tiempo, probablemente obtendrá un patrón de "diente de sierra", como la memoria sube con el tiempo, pero luego tiene afilada drop-offs cuando se ejecuta el recolector de basura. Puede intentar "sugerir" la recolección de basura haciendo clic en el botón etiquetado.

Al hacer esto, ¿el uso de memoria se reduce al mismo nivel mínimo, o el mínimo general aumenta a lo largo de varios minutos? Si el uso mínimo aumenta, entonces tiene una pérdida de memoria.Si siempre vuelve al mismo nivel mínimo, entonces estás bien.

+1

esta fue una respuesta muy perspicaz. ¡Voy a darle una oportunidad! –

+1

Le di una oportunidad a JConsole y es una utilidad bastante ingeniosa. Mientras miraba, el uso de memoria de montón siguió aumentando. Cuando invoqué el GC (con el botón que mencionas), el uso de la memoria tocó fondo. Intenté esto varias veces y siempre bajó a aproximadamente el mismo nivel mínimo. Muchas gracias! –

+2

Tenga en cuenta que JDK 6 tiene una utilidad niftier par: JVisualVM. Comience escribiendo el comando 'jvisualvm' en el símbolo del sistema. – Jesper

2

¡Felicidades en su primera aplicación! Ahora, un par de cosas en que pensar. Primero, el administrador de tareas de Windows no es un gran recurso para comprender qué tan rápido está creciendo su VM. En su lugar, debe supervisar sus estadísticas de recolección de basura en la consola (use el parámetro de línea de comandos -verbose:gc). En segundo lugar, si le preocupan las fugas potenciales y el crecimiento de la VM, hay muchos grandes perfiladores que son fáciles de usar y pueden ayudarlo a diagnosticar problemas de memoria. echa un vistazo a estos twoposts para algunas opciones del perfilador.

+1

@afk, ¡Gracias! He oído que el Administrador de tareas de Windows no era la mejor herramienta para monitorear aplicaciones Java, pero no sabía cuán confiable era esa información. Bien, reviso lo que has mencionado. –

2

¡Felicitaciones por su primera aplicación Java!

Las aplicaciones Java se ejecutan en una máquina virtual. El sistema operativo ha asignado a la máquina virtual una cantidad fija de memoria, generalmente 512 MB. Siempre que la aplicación use menos de 512 MB, el recolector de basura no se activará y comenzará la búsqueda de bloques de memoria "muertos". El límite de memoria de JVM se puede modificar en la mayoría de los sistemas operativos. Intente cambiar el límite de memoria a 32 MB, por ejemplo.

+1

gracias !! Voy a tener esto en cuenta. Voy a tratar de ver qué tan lejos realmente sube. Gracias por las sugerencias. –

+0

básicamente correcto, pero ninguna JVM con la que me haya encontrado asignará un montón inicial tan grande (512Mb) ... a menos que algo específicamente lo indique a través de las opciones de lanzamiento de JVM. –

1

¿Es este el comportamiento normal de Java?

No.

supongo que es posible que mi código podría ser una fuga de memoria

Eso es sin duda la causa. Por favor, publique su código fuente; de ​​lo contrario, no será posible realizar un nuevo diagnóstico.

Me di cuenta de que está utilizando Swing, asegúrese de que está iniciando su JFrame en el event dispatch thread, utilizando el método invokeLater(Runnable).

Si está utilizando cualquier tipo de colecciones, asegúrese de que clear una vez hecho.

Ya que está haciendo algo de IO de archivo, asegúrese de cerrar todas las clases involucradas en las operaciones IO después de que haya terminado con ellas.

Si está utilizando cualquier detector de eventos, recuerde eliminar explícitamente los detectores de eventos cuando ya no sean necesarios.


Una cosa que podría intentar es experimentar. Tome su aplicación y elimine el archivo IO, vea qué sucede. ¿El uso de la memoria todavía sube como antes? Ahora resintonice su aplicación a la normalidad y elimine el área de texto. ¿La memoria todavía sube como antes? Etc, etc. Esto te ayudará a determinar cuál es la fuente, y puedes enfocar tus esfuerzos allí. Lo más probable es que descubras lo que buscas haciendo esto.

Otra herramienta de diagnóstico útil es utilizar System.gc() en determinados momentos en el tiempo, por lo general después de los bloques de código de elevación pesada. Esto le indicará a la JVM que realice una recolección de basura en ese punto de la ejecución, en lugar de hacerlo en otro momento determinado por el consumo de memoria. Esto lo ayudará a tener en cuenta cualquier fluctuación periódica en el uso de memoria de su aplicación.

En caso contrario, siempre puede usar un generador de perfiles de memoria. Si está utilizando Netbeans IDE, hay uno integrado en él. Para Eclipse, hay varios complementos que pueden realizar perfiles.

+1

¿Cómo es útil? –

+0

Sí, esto es Java. Tratar con él. – matiasf

+1

@bguiz No estoy seguro de entender lo que quiere decir con el hilo de envío del evento. Soy muy nuevo en Java y no he visto eso mencionado. –

1

es normal. algunos antecedentes pueden dejar objetos muertos, lo que JVM no tiene prisa por limpiar. con el tiempo serán recogidos basura, cuando se llegue a max mem.

deje su programa funcionando durante la noche, y su máquina no explotará.

+1

gracias, lo tendré en cuenta. –

Cuestiones relacionadas