¿Go está sujeto a las mismas pérdidas de memoria sutiles que Java?

89

Aquí están los hechos:

  • el idioma Go tiene un recolector de basura.

  • Java tiene una recolección de basura

  • muchos programas Java tienen (sutiles o no) pérdidas de memoria

Como ejemplo de un programa Java que tiene pérdidas de memoria (no es para los débiles de corazón, la pregunta puede afectar sus creencias), vea aquí un pequeño programa Java llamado Tomcat que incluso tiene un botón para "buscar pérdidas": ¿Hay alguna manera para evitar pérdidas de memoria de anulación de implementación en Tomcat?

Entonces me pregunto: ¿los programas escritos en Go exhibirán el mismo tipo de pérdidas de memoria (sutiles o no) que exhiben algunos programas escritos en Java?

Sintaxis T3rr0r
fuente
29
"muchos programas Java tienen (sutiles o no) pérdidas de memoria" ¿tiene alguna evidencia de este "hecho" o es sólo un tema de conversación?
Peter Lawrey
17
@Webinator: Creo que debe dar un ejemplo de una de estas "pérdidas sutiles de memoria" que tienen "muchos" programas Java. A menos que esté reclamando un error en el recolector de basura, la única forma de perder memoria en Java puro es aferrarse a las referencias que ya no está usando, por ejemplo, poniendo objetos en una colección y nunca eliminándolos de esa colección. Si este es el tipo de filtración a la que te refieres, ningún idioma en el mundo te protegerá contra ellos, incluido Go.
JeremyP
14
Aquí están las fugas de memoria de las que estaba hablando (+200 upvotes, respuestas con +150 upvotes, muchas fugas de memoria Java explicadas): stackoverflow.com/questions/6470651/…
SyntaxT3rr0r
6
Por supuesto, los programas JAVA tienen pérdidas de memoria, solo olvídese de establecer alguna referencia en nulo cuando ya no los necesite. Ocurre con frecuencia en grandes colecciones persistentes (como cachés), con patrón de diseño de observador o variables locales de subproceso. Esto no es teórico, yo mismo corrigí varias fugas de memoria en producción. Y esto no es anti Java. Soy un desarrollador de JAVA a tiempo completo durante más de 5 años, he estado trabajando en muchos proyectos diferentes. No reconocer que puede tener pérdida de memoria en JAVA (o en cualquier otro lenguaje existente) no es fanboyismo, es más falta de comprensión de cómo funcionan realmente las cosas.
Nicolas Bousquet
6
Esta pregunta podría prescindir del drama y los comentarios sobre "fanboyismo", "sacudir las creencias de alguien" y cosas por el estilo. Esp. ya que toda la discusión se reduce a "mi definición de memory leakes mejor que la tuya".
LAFK dice Reincorporar a Monica

Respuestas:

44

Estás confundiendo diferentes tipos de fugas de memoria aquí.

Las atroces fugas de memoria basadas en la gestión de memoria explícita se han ido en Java (o cualquier otro lenguaje basado en GC). Estas fugas se deben a la pérdida total de acceso a fragmentos de memoria sin marcarlos como no utilizados.

Las "fugas de memoria" todavía presentes en Java y todos los demás lenguajes del planeta hasta que la computadora pueda leer nuestras mentes todavía están con nosotros, y lo estarán en el futuro previsible. Estas fugas son causadas por el código / programador que mantiene referencias a objetos que técnicamente ya no son necesarios. Estos son errores fundamentalmente lógicos y no se pueden prevenir en ningún idioma utilizando las tecnologías actuales.

James
fuente
23
La pérdida de memoria es simplemente cuando se olvida de liberar memoria. En Java, esto ocurre cuando olvida establecer referencias a nulo. En C ++ sucede si olvidas llamar gratis. Ambos son casos válidos de pérdida de memoria. Y el problema fundamental es el mismo, su programa consume cada vez más memoria hasta que finalmente se bloquea con un error OutOfMemory.
Nicolas Bousquet
1
Si bien es cierto que ningún lenguaje puede evitar que el programador cometa tales errores lógicos, también es cierto que algunos de esos errores existen en el propio SDK de Java (ver, por ejemplo, java.util.logging.Levelque contiene una estática privada ArrayListen la que todos los objetos construidos son colocados en construcción, y de los cuales nunca se eliminan), lo que hace que sea más difícil evitarlos al programar Java que en algún otro lenguaje que no contenga tales fallas
Jules
7
Creo que el OP estaba preguntando sobre fugas de memoria de objetos que realmente son inalcanzables, como en la respuesta aceptada de la pregunta vinculada. La pérdida de memoria causada por la carga de clases desde subprocesos. -1
qbt937
1
También es concebible que el análisis estático pueda determinar si las referencias continúan existiendo más allá de su vida útil, sin necesidad de leer la mente.
Kyle Strand
1
@Amrit No, el recolector de basura recolecta memoria a la que ya no tienes referencias. No tiene forma de saber si está bien eliminar algo a lo que todavía tiene una referencia.
Raphael Schmitz
19

Es muy posible que los programas Go presenten pérdidas de memoria. La implementación actual de Go tiene un recolector de basura simple de marcar y barrer. Esto solo está pensado como una solución temporal y no como un recolector de basura a largo plazo. Consulte esta página para obtener más información. Mire debajo del encabezado Go Garbage Collector. Esa página incluso tiene un enlace para codificar la versión actual si así lo desea.

Poindexter
fuente
1
Uno de los problemas del recopilador de marcas y barridos en Java es la fragmentación de la memoria. Aunque técnicamente no es una memoria, puede ser una pérdida de memoria disponible para la aplicación.
Peter Lawrey
9

Una 'pérdida de memoria' es cuando una parte de la memoria que el programador pensó que se liberaría no se libera. Esto puede suceder en cualquier idioma, recolección de basura o no. La causa habitual en los lenguajes GC es retener una referencia adicional a la memoria.

"Los lenguajes no provocan pérdidas de memoria, los programadores provocan pérdidas de memoria".

DJClayworth
fuente
8

Recolección de basura o no, puede escribir un programa que tenga pérdidas de memoria en Java, Go o cualquier otro lenguaje en su mayor parte.

Garbage Collection le quita parte de la carga al programador, pero no evita las fugas por completo.

jzd
fuente
4
Sé que sé. Me refiero específicamente a las pérdidas de memoria un poco sutiles que existen en Java, incluso cuando Java fue, al principio, comercializado como un lenguaje donde las pérdidas de memoria no existen gracias al GC .
Sintaxis T3rr0r
4
Lamento que no haya quedado claro. Dijiste "muchos programas Java tienen (sutiles o no) pérdidas de memoria".
jzd
3

Aquí está mezclando niveles de abstracción: las pérdidas de memoria se deben a errores en la biblioteca (donde los objetos se referencian entre sí a través de cadenas de 'a mantiene referencia a b' así como una compensación en la implementación del recolector de basura entre eficiencia y precisión. ¿Cuánto tiempo desea dedicar a descubrir estos bucles? Si gasta el doble, podrá detectar bucles el doble de tiempo.

Entonces, el problema de la pérdida de memoria no es específico del lenguaje de programación, no hay ninguna razón por la que GO por sí solo deba ser mejor o peor que Java.

florín
fuente
1
No estoy del todo de acuerdo. Las pérdidas de memoria se deben al hecho de que Java permite dispararse a uno mismo en el pie y no está necesariamente relacionado con errores de bibliotecas. Muchos programadores escriben programas que pierden memoria lenta pero seguramente en Java y eso es culpa suya, no de las bibliotecas. Además, si precisamente Java GC está haciendo una compensación de tiempo / posible fuga, ¿Go está haciendo las mismas compensaciones?
Sintaxis T3rr0r
1
y la pregunta realmente no es "¿cuánto tiempo quiero dedicar a descubrir esos bucles?" La pregunta es "¿Cuánto tiempo las especificaciones obligan a que Go GC gaste en tales bucles" , que en mi humilde opinión es una pregunta interesante.
Sintaxis T3rr0r
16
Las cadenas de referencia cíclicas no evitan la recolección de basura en Java.
Andy Thomas