Question

I have a basic question. Consider this simple code:

class A{
   void someMethod(){
      B b = new B(); // Line 3
      B c = new B(); // Line 4
   }
}

When Line 3 is executed, class B is loaded into memory (i.e.: we have physical space allocated for a object of type 'Class' ( Let's say with an id - classLaoder1.B) of type class containing code for class B).

Question 1# What happens next? - Instance of class B(representing state of b) is created(allocated physical memory) based on the fact that classLoader.B actually contains B's information?

Question 2# Also, at Line -4, the since classLoader.B is present in memory, an object containing state of c is created in memory?

Was it helpful?

Solution

Well, your example and the description are a bit to vague to answer your question in a short manner.

You are referring to different classloaders but you didn't include any exemplary code when which class is loaded. In its current form the code won't even compile as the return value is missing - but let's continue with your question.

The heap is a memory area created by the JVM at startup and may increase and decrease at runtime dynamically. It is divided into different sections. YoungGen will hold short lived objects, OldGen will hold object states of objects that survived the YoungGen space and finally the PermGen space which as it names suggest should contain permanent class metadata and descriptors. Therefore, the PermGen space is reserved for classes and stuff that is tied to classes (like static members) and you will have to deal with it if you handle application servers or plugin-mechanisms that provide some kind of hot-deployment features. (To be a bit more precise, in Sun's JVM the PermGen space is actually a separate part of memory and does not really belong to the heap, but different JVM vendors may have different definitions therefore)

enter image description here Reference: Configuration and Setup of SAP JVM

Two cases may occur upon invoking someMethod():

  • B was already loaded by the application classloader on startup of your application
  • B is included within a class that got loaded by a child classloader

In the first case the memory for the class definition is allocated at startup within the PermGen space of the heap and is only freed when the application shuts down. In the latter case, there is also memory for that class stored in the PermGen space of the heap, but on invoking loadClass(...) of the class-loader which should load the class. Here, memory can be freed if no strong reference is pointing to any class loaded by that class-loader. Often, enums or singleton classes, which hold a strong reference to themselves, will prevent however a correct unloading of those loaded bytes and create a memory leak therefore.

If you ever implement one of those application-frameworks and debug it, you will see what exactly happens when. To load a class via a class-loader the loadClass(...) method is called which first checks if it already has loaded that class before then asks his parent if she knows this class (which also checks if she has loaded that class or her parent, ...). Only if the class was not loaded before (by either this class-loader or any parent) the current (child) class-loader is going to execute findClass(...) which further should call defineClass() which actually turns the bytes from some input-file or stream to a Class representation. That Class object contains the blueprint (signature of the method including number and type of parameters, return value and thrown exceptions). On trying to load a class, usually the extension class as well as the defined interfaces get loaded too (if not already known in the class-loader tree) - but the types of including members are not yet loaded! They will get loaded when the class is going to be instantiated.

enter image description here Reference: How ClassLoader Works in Java

On creating a new instance, the new operator invokes the newInstance(...) method internally and reserves memory for all members of that instance. So, if the type of the member is yet unknown by the current class-loader or its parents, it will be loaded before assigning any values. Then, the constructor of the class is executed (according to the constructor called with the new operation) and values get assigned to the memory occupied by the variables on the heap (often in Eden space). After the object is constructed in memory, a reference to the object is returned by the new operator and the object is ready to be used within your code.

c in your example is instantiated the same way as b - first the classloader has to check if class B was already loaded. As it has loaded B before, it just grabs B from its local cache and returns the class therefore. Next, the newInstance(...) method is executed on the class to instantiate a new object. Therefore, again memory for the member variables is allocated on the heap - after the initial check if the required classes have already been loaded - the constructor is executed and the reference to the newly created and initialized object is returned.

If your class has static methods or static members they will get allocated onto the PermGen space, as they belong to the class and are shared across all instances.

One thing to note: If c should be loaded by a peer or peer's child class-loader (CL2) and b was defined by a sister class-loader (CL1) (so no parent has actually defined the class), the peer class-loader CL2 will load (and define) its own version of B which seems to be the same as the version of the sister's loader CL1, but they actually are different classes for Java as the class-loader which loaded that class is actually part of the class. This means CL1-B != CL2-B although both versions share the same methods and fields. Casting c to b's B will result in a ClassCastException therefore.

Just for completeness, although you didn't ask for this, on calling methods a different kind of memory allocation occurs. The passed variables are pushed onto the stack, which every thread has its own instance of, and popped from the stack (including return value) if the method returns. Furthermore, each block (The part between { and }) creates a new stack-frame (that's why variables declared inside a block are not visible to a region outside of the block) where the local variables of that block are stored into. More information available here

enter image description here Reference: Understanding Stack and Heap-Tutorial

OTHER TIPS

b and c are instances of the Class B, consider them variables, so they will be stored in memory separately. b contains information of the class B (the class is equivalent to a structure) so you may have a class Person that has the variable name, and you have 2 instances: p1 and p2. Each one will have a different name and a different place in memory

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top