2010-04-09 24 views
7

Java tiene su propia implementación de recolección de basura por lo que no requiere ningún destructor como C++. Esto hace que el desarrollador de Java sea perezoso al implementar la administración de la memoria.¿Por qué Java no tiene ningún destructor como C++?

Todavía podemos tener destructor junto con recolector de basura donde el desarrollador puede liberar recursos y que puede salvar el trabajo del recolector de basura. Esto podría mejorar el rendimiento de la aplicación. ¿Por qué Java no proporciona ningún tipo de mecanismo destructor?

desarrollador no tiene control sobre GC pero él/ella puede controlar o crear el objeto. Entonces ¿por qué no les da la capacidad de destruir los objetos?

+6

Su pregunta también tiene la respuesta. En lugar de destructor, java realiza las recolecciones de basura – Venkat

+22

-1 para reclamos sin fundamento en la recolección de basura. – SteveD

+0

@stevendick Aquí trato de entender solo la diferencia entre GC y Destructor. –

Respuesta

54

Usted está afirmando que "la recolección de basura es muy costosa". ¿Podría respaldarlo con evidencia? La recolección de basura ciertamente no es gratis pero los recolectores de basura modernos son muy buenos.

Tenga en cuenta que una de las formas en que el GC puede ser eficiente es que sabe es lo único que hace asignación de memoria y desasignación (para objetos administrados). Permitir que un desarrollador explicitamente liberar un objeto podría obstaculizar esa eficiencia. También había necesidad de preocuparse de lo que sucedería si un desarrollador trató de "utilizar" a un objeto liberado:

Foo f = new Foo(); 
Foo g = f; 
free(f); // Or whatever 
System.out.println(g.toString()); // What should this do? 

¿Usted está proponiendo que cada objeto debe tener una bandera adicional para "ha sido explícitamente esta liberado", que necesita ser revisado en cada referencia? Esto parece una receta para el desastre, para ser honesto.

Tienes razón, permite a los desarrolladores de Java ser perezoso en esta área. Eso es bueno. Los IDE les permiten a los desarrolladores ser perezosos también, al igual que los lenguajes de alto nivel, etc. La pereza en la asignación de memoria permite a los desarrolladores en entornos administrados gastar su energía preocupándose por los problemas de negocios en lugar de la administración de la memoria.

+0

Creo que los desarrolladores son flojos (en el buen sentido) ¡por naturaleza! –

+24

'free' is not * free * tampoco. –

+0

@ TomHawtin-tackline Como dijo un hombre, si algo es gratis, significa que eres el producto :) –

-2

Tienes la capacidad de controlar la destrucción de objetos en Java. Simplemente utiliza un lenguaje diferente:

Connection conn = null; 
try { 
    conn = ... 
    // do stuff 
} finally { 
    try { conn.close(); } catch (Exception e) { } 
} 

Usted podría señalar en este punto que esto no es objeto de destrucción y que podría, por ejemplo, pasar ese objeto a otra cosa y aún así tener una referencia a él. Usted tiene razón en ambos aspectos. Es simplemente lo más cercano que se obtiene Java (y la mayoría de las plataformas administradas).

Pero no Java, como usted dice, no tiene un mecanismo destructor como en C++. Algunas personas confunden a los finalizadores por esto. Son destructores no y es peligroso usarlos como tales.

La gestión de memoria para un programador es difícil. Puede perder fácilmente la memoria, especialmente al realizar una programación multiproceso (también difícil). La experiencia ha demostrado que el costo de GC, aunque real y en ocasiones sustancial, está bien justificado en aumentos de productividad e incidencias de errores en la gran mayoría de los casos, razón por la cual la gran mayoría de las plataformas ahora están "administradas" (lo que significa que usan recolección de basura).

+9

Eso no destruye el * objeto * - libera algunos recursos asociados con el objeto (el manejador del sistema operativo subyacente, presumiblemente) pero no el objeto en sí. –

1

Si sabe que ya no hace grandes objetos, simplemente establezca las referencias a ellos como nulas. Esto podría acelerar la recolección de basura de estos objetos.

+2

Muy rara vez es una buena idea, IMO. En la mayoría de los casos, el recolector de basura es lo suficientemente inteligente como para resolver esto por usted, y desordena su código. Hay algunas excepciones, pero no son muy comunes en mi experiencia. –

+0

Eso es correcto. En la mayoría de los casos, no necesita esto, pero es una posibilidad para el programador que cree que podría engañar a algo de Java para hacer algo como liberar un recuerdo. – Janusz

+0

Es al menos una indicación de lo que quiere, incluso si Java lo ignora o lo optimiza. Y hará que más errores de implementación generen una excepción, que es una buena cosa. Es posible una aceleración de GC, dependiendo del algoritmo que use la implementación de VM, pero esa no debería ser una razón para hacer esto. – foo

7

El destructor C++ no es una forma de destruir objetos; es un conjunto de operaciones que se deben realizar cuando el objeto se destruye. En Java, no tiene control sobre el momento en que los objetos son destruidos (ni siquiera pueden ser destruidos), por lo que se desaconseja poner cualquier código importante que se ejecute en la destrucción del objeto (aunque es posible - finalize método). Si no pide un destructor sino una forma de destruir explícitamente el objeto dado, está invitando a referencias colgantes en su código. Ellos no son bienvenidos.

+4

C++ no le da "ningún control sobre el momento en que los objetos son destruidos". C++ utiliza la finalización determinista. Cuando elimina un objeto, su destructor se llama inmediatamente y luego su almacenamiento se desasigna inmediatamente. No hay C++ GC. No estoy diciendo que esto sea necesariamente algo bueno, pero es cómo funciona C++. –

+2

@andyjohnson: O me malinterpretaste o mi gramática se rompió. De todos modos intenté arreglarlo. No hay control en el momento en que se destruyen los objetos en Java. En C++ usted tiene control total sobre él (reglas modulo complicadas sobre la duración de los temporales). –

+0

@andyjohnson: El almacenamiento es inmemorialmente _unavailable_. La _deallocación_ real puede ocurrir más tarde - el procesamiento por lotes no es desconocido. – MSalters

21

La recolección de basura es muy costosa.

De hecho, para aplicaciones complejas, el rendimiento de la recolección de basura es competitivo con gestión de almacenaje manual basado en malloc/free. Existe un artículo clásico por Benjamin Zorn que lo demuestra claramente. En este documento, Zorn describe cómo modificó algunas aplicaciones de gran uso intensivo de montón para utilizar un recolector de basura conservador en lugar de malloc y free. Luego comparó las versiones originales y modificadas de las aplicaciones. El resultado fue un rendimiento comparable.

Este artículo fue publicado en Software Practice and Experience en 1993. Si no lo ha leído, no está calificado para pronunciarse sobre la "ineficiencia" de la recolección de basura.

Tenga en cuenta que esta investigación se realizó con un 1993-vintage conservador recolector de basura. Un recolector conservador es marcado sin compactación; es decir, los objetos que no son basura no se mueven. Esto último significa que la asignación de espacio para objetos nuevos es tan lenta y complicada como malloc. Por el contrario, los recolectores de basura modernos (por ejemplo, Java 6/7) son colectores de copias generacionales que son mucho más eficientes. Y dado que la copia compacta los objetos restantes que no son basura, la asignación es mucho más rápida. Esto hace que GC sea aún más competitivo ... si se pudiera encontrar una manera de hacer la comparación.


desarrollador no tiene control sobre GC, pero él/ella puede controlar o crear el objeto. Entonces, ¿por qué no darles la capacidad de destruir los objetos?

Depende de qué es exactamente lo que quiere decir con "destruct".

  • En Java, usted tiene la posibilidad de asignar null. En algunas circunstancias, esto puede acelerar la destrucción de un objeto.

  • En Java, puede utilizar finalizadores y Reference tipos para darse cuenta de que un objeto está a punto de destruirse ... y algo sobre eso.

  • En Java, puede definir un método close() (o equivalente) en cualquier objeto y hacer que haga algo apropiado. Luego llámalo explícitamente.

  • En Java 7, tiene la construcción "intentar con recursos" para llamar automáticamente al close() en los recursos en la salida del alcance.

Sin embargo, no puede hacer que un objeto Java se elimine AHORA. La razón por la que esto no está permitido es que permitiría a un programa crear referencias colgantes, lo que podría conducir a la corrupción del montón y bloqueos aleatorios de JVM.

Esa NO es la forma de Java. La filosofía es que escribir programas confiables es más importante que la eficiencia. Si bien ciertos aspectos de Java no siguen esto (por ejemplo, subprocesamiento), nadie quiere la posibilidad de bloqueos JVM aleatorios.

+2

@Abhishek: Si * esperaba * una respuesta que impugnara su afirmación, ¿por qué lo incluyó como una afirmación para empezar? ¿Por qué no solo pregunta "¿Es cara la recolección de basura?" Eso vendría como menos argumentativo, IMO. –

+0

En realidad, no estoy * solo * disputando la afirmación. También estoy proporcionando una referencia a pruebas contundentes de que (IMO) * lo desmiente *. –

+0

Para el votante anónimo al azar: no dude en explicar por qué cree que es una mala respuesta. –

5

Esto hace que Java developer lazy en implementando la gestión de memoria.

No, los libera para realizar trabajo útil.

y recolección de basura es muy caro .

Comparado con qué? ¿Hechos? Cifras? Tienes unos 20 años fuera de fecha con ese comentario. El uso solo de Java refuta efectivamente esa afirmación.

Esto podría mejorar el rendimiento de la aplicación.

O no. ¿Tenías algunos hechos para aducir?

Entonces, ¿por qué no les da la capacidad de destruir los objetos?

¿Porque no es obligatorio?

+0

"no es necesario" Bueno, ¿cómo se puede llamar a su código de limpieza? Java no garantiza nada en finalize(). Puede tener toda la inicialización en el constructor que desee, pero para las * actividades * de limpieza, Java no ofrece nada. – foo

+0

@foo al contrario. Java ofrece el bloque finally {}. – EJP

+0

Si insiste en la verbosidad: Java no garantiza el método finalize(), y no tiene nada que ofrecer con respecto a la destrucción confiable de objetos. (Sí, en el nivel de bloque de control, está el bloque finally, que es bastante inútil para el ciclo de vida del objeto.) – foo

1

El destructor C++ no es una forma de destruir objetos: es un conjunto de operaciones que se deben realizar cuando el objeto se destruye.

Creo que está confundiendo la terminología. Así es como yo lo veo:

crear objeto = primera asignar memoria, entonces construir través constructor

destruir objeto = primera destrucción través destructor, a continuación, liberar memoria

Cómo la memoria es asignada y desasignada depende. Si usa new y delete, la administración de memoria se realiza por void* operator new(size_t) y void operator delete(void*).

4

destructores son llamados cuando el objeto se destruye en C++, no destruir el objeto. Si desea garantizar la limpieza, haga que el usuario llame a un método Destruir o similar.

+1

No puede * hacer * que el usuario llame a un método Destruir(). Si necesita control para liberar adecuadamente los recursos internos asociados con el objeto, entonces necesita algo de método (como un destructor) que se llama implícitamente. – jarmod

+0

@jarmod Si el usuario NO llama a Destroy(), entonces filtra un recurso. Quise decir algo como 'IDispose' en .NET. Llama a 'Dispose()' para eliminar un objeto de manera explícita. – quantum

0

Un destructor de C++ es útil para liberar cualquier recurso propiedad del objeto, no solo de la memoria. Puede ser archivos, sockets, mutexes, semáforos o cualquier otro manejador de recursos. Usar un destructor es una forma inteligente de evitar fugas de recursos. Envuelva el manejo de recursos en una clase de C++ y cree un destructor que libere los recursos asignados. No veo ningún método en Java. Tienes que liberar explícitamente el recurso, y esto puede ser complicado si hay muchas rutas de salida posibles.

0

No, java no es compatible con destructores. Toda la tarea de liberar la memoria se hace por GARBAGE COLLECTOR.

Java tiene su propia característica de administración de memoria utilizando el recolector de basura. Cuando utiliza finalize(), el objeto queda disponible para la recolección de basura y no necesita llamar explícitamente al destructor. C# y Java no quieren que te preocupes por el destructor ya que tienen características de recolección de basura.

Java es un lenguaje de bytecode, tiene una detección de basura muy fuerte. Si permitiera que las personas definan sus propios destructores, es probable que cometan algunos errores. Al automatizar el proceso, Java tiene la intención de prevenir esos errores.

Cuestiones relacionadas