Cuando creo un objeto, se asigna memoria nueva a los campos y métodos de instancia o solo a los campos de instancia

14

Tengo una clase siguiente

class Student{

int rollNumber;
int marks;

public void setResult(int rollNumber, int marks){

    this.rollNumber=rollNumber;
    this.marks=marks;   
}

public void displayResult(){

    System.out.println("Roll Number= "+this.rollNumber+"   Marks= "+this.marks);

}
}

Ahora creo dos objetos de tipo Estudiante de la siguiente manera

Student s1=new Student();
Student s2=new Student();

Ahora se asignan dos conjuntos diferentes de memoria para campos de instancia. Ahora mi pregunta es si la memoria se asigna para los métodos ( setResulty displayResult) dos o una vez.

Consulte la siguiente figura y ¿puede ayudarme a decir qué figura proporciona la información correcta?

ingrese la descripción de la imagen aquí

Harish_N
fuente
1
Compartir su investigación ayuda a todos . Cuéntanos qué has probado y por qué no satisfizo tus necesidades. Esto demuestra que te has tomado el tiempo para tratar de ayudarte a ti mismo, nos salva de reiterar respuestas obvias y, sobre todo, te ayuda a obtener una respuesta más específica y relevante. También vea Cómo preguntar
mosquito el
3
Estoy aprendiendo Java ... y en todos los materiales solo dicen que cada vez que creamos un objeto, se asigna una memoria nueva a todos los campos de instancia ... pero ninguno de los materiales dice si se asignará memoria nueva para métodos o no
Harish_N

Respuestas:

13

El código para los métodos es parte de Class(más concisamente Class<Student>) y se carga en la memoria cuando la clase se carga por primera vez.

Dicho esto, cuando ejecuta cualquier método, se utiliza memoria adicional para asignar memoria a parámetros, variables locales, resultados de expresiones temporales, valores de retorno, etc. Pero dicha memoria se asigna en la pila (la memoria utilizada al crear una nueva instancia se asigna en el montón .

Según su pregunta, debe quedar claro ahora que la figura B es correcta (aunque no refleja lo que sucede cuando realmente llama al método).

SJuan76
fuente
Okay. Ahora estoy 90% claro ... Pero una pequeña duda ... Supongamos que si creo 10 objetos del tipo Estudiante, solo se asigna 1 conjunto de memoria nueva a los métodos presentes en la clase Estudiante, mientras que 10 conjuntos de memoria nueva son asignado para almacenar variables de instancia para 10 objetos ... ¿Estoy en lo cierto?
Harish_N
Correcto. Piense que no son solo las propiedades las que toman memoria, hay una pequeña sobrecarga relacionada con la instancia en sí (una instancia de una clase sin propiedades usará más de 0 bytes de memoria).
SJuan76
Una cosa más ... hice una pregunta teniendo en cuenta a Java ... ¿Sucede lo mismo en Java .....
Harish_N
La especificación del lenguaje Java no dice nada acerca de cuánta memoria se asigna cuándo y con qué propósito. Eso se deja al implementador, y cada implementador puede elegir de manera diferente.
Jörg W Mittag
6

Los campos de instancia (incluidos los campos de respaldo de propiedad) obtienen N-copias para N-objetos.

Los campos estáticos obtienen una sola copia por clase.

Los métodos son bloques de bytecode (o después de JIT, bloques de instrucciones nativas) que forman parte del programa "imagen" o segmento de código ejecutable. Los métodos ya son parte de la imagen del programa, ya que se encuentra en el disco. Una vez que el sistema operativo (o CLR) carga la imagen, hay una única copia compartida del código del método.

No son parte de la asignación de "montón" o tiempo de ejecución en general, excepto en los casos en que puede utilizar el compilador hospedable para compilar nuevos métodos sobre la marcha. Los métodos no se "asignan" como objetos y no se "asignan" en relación con la creación del objeto. Simplemente existen como parte del programa antes de que un solo objeto sea instanciado. Incluso las lambdas / delegados no se asignan sobre la marcha. El compilador crea clases a pedido para implementar estos otros objetos de código aparentemente dinámicos, y también existen como parte de la imagen de código de bytes en el disco.

ACTUALIZACIONES por comentarios:

El estándar JVM tiene esto que decir:

2.5.4. Área de método

Java Virtual Machine tiene un área de método que se comparte entre todos los subprocesos de Java Virtual Machine. El área del método es análoga al área de almacenamiento para el código compilado de un lenguaje convencional o análogo al segmento de "texto" en un proceso del sistema operativo. Almacena estructuras por clase, como el grupo constante de tiempo de ejecución, los datos de campo y método, y el código para métodos y constructores, incluidos los métodos especiales (§2.9) utilizados en la inicialización de clase e instancia y la inicialización de interfaz.

El área de método se crea al iniciar la máquina virtual. Aunque el área del método es lógicamente parte del montón, las implementaciones simples pueden elegir no recolectar basura ni compactarla. Esta versión de la especificación de Java Virtual Machine no exige la ubicación del área de método o las políticas utilizadas para administrar el código compilado. El área del método puede ser de un tamaño fijo o puede expandirse según lo requiera el cálculo y puede contraerse si un área del método más grande se vuelve innecesaria. La memoria para el área de método no necesita ser contigua.

Por lo tanto, está claro que (1) sí, la especificación no dicta cómo se hace, pero (2) es análoga al área de almacenamiento para el código compilado de un lenguaje convencional, es decir. El segmento de texto. Este es el punto que estoy haciendo.

Codenheim
fuente
Lo que estás diciendo tiene sentido, pero ¿está eso realmente garantizado por el JLS? Normalmente, el JLS le da a los implementadores mucho margen de maniobra en preguntas como esta.
Jörg W Mittag
No estoy seguro sobre ese punto, @ JörgWMittag. Puede que tengas razón. El punto que intenté hacer es que "new T ()" no asigna una nueva instancia de un método. En cuanto a los detalles de la JVM, los cargadores de clases almacenan de hecho bytecode en el montón, y supongo que hay posibles escenarios en los que las clases se instancian e incluso se recolecta basura. Pero es el detalle de implementación del tiempo de ejecución, y conceptualmente, el montón del que estoy hablando es el montón "usuario". La clase y los métodos no se consideran datos en el contexto normal del usuario. Pero como también podemos controlar un cargador de clases desde userland, supongo que no lo sé.
codenheim
El JLS ni siquiera habla de un montón, ¿no? Es perfectamente legal implementar Java con una pila dinámica y sin montón en lugar de una pila finita de tamaño fijo y un montón dinámico. El JLS tampoco dice nada sobre la JVM, es perfectamente válido implementar Java sin una JVM.
Jörg W Mittag
Estás haciendo referencia a JLS, pero estoy hablando de JVM. El estándar JVM ciertamente discute el montón. Debe proporcionar un alcance / duración variable que escape al alcance local de la pila. En cuanto a lo que es teóricamente posible, prefiero pensar en términos de "implementaciones conocidas". Estoy bastante seguro de que implementar una JVM completa sin una primitiva de montón es un trabajo difícil, o incluso imposible, ya que la JVM no es una máquina de pila pura. Comprendo que las máquinas Forth y otras arquitecturas de pila pura son posibles si existe una primitiva para el acceso variable aleatorio, pero simplemente no la he visto.
codenheim
@ JörgWMittag: agregué a la respuesta algo que puede ser de interés para nuestra discusión. El punto es que estaba dibujando una analogía con el segmento tradicional de código o texto en los sistemas de tiempo de ejecución convencionales.
codenheim
-4

objeto asignado en la memoria de almacenamiento dinámico. cuando se asignan los objetos, la ranura para toda la variable de instancia se crea y se destruye cuando se destruye el objeto. por lo tanto, la variable de instancia también se asigna en la memoria de almacenamiento dinámico. Se llaman método.

Abhishek Tripathi
fuente
1
Esto parece repetir la información que se proporciona en las respuestas anteriores.