1

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?

sofs1
  • 3,834
  • 11
  • 51
  • 89
Java User
  • 127
  • 3
  • 9
  • 1
    This sample code has lots of syntactic errors and your question is poorly formed. Please rephrase your question and maybe be careful to distinguish between classes and instances of classes. – Mike Samuel Jan 27 '14 at 00:24
  • Actually, Class B is loaded when Class A is verified, which occurs sometime before your method begins executing. Instances of B are created when the two `new` operations execute. The B Class object is referenced to see how to create the new instances, and a pointer to the B Class object is placed in each instance so methods can be located, etc. – Hot Licks Jan 27 '14 at 01:29
  • Thanks, this helps. One more question please: What all is contained inside instances( in this example - b and c)? – Java User Jan 27 '14 at 02:04
  • An "instance" contains a pointer to the Class object (or, actually, a pointer to a C-language struct that contains the "real" Class data), a "lock" variable (used for `synchronized` operations), a set of flags used by GC, and space for the instance fields. It's fairly "lightweight". – Hot Licks Jan 27 '14 at 02:34

2 Answers2

7

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

Community
  • 1
  • 1
Roman Vottner
  • 12,213
  • 5
  • 46
  • 63
  • Thank you for the detailed explanation. It's really great and very helpful. Could you please help me understand the below. 1. "B was already loaded by the application classloader on startup of your application" - When will this occur? When B.java has a main method and it's invoked? 2. Does the Class definition of B contains only the blueprint of B (its methods outline) or the method definition(body of method) as well? – Java User Jan 27 '14 at 03:38
  • 1) If you use no class-loaders at all or those classes that are not loaded by a custom-classloader will get loaded automatically by the application class-loader or any parent on execution of `new` operations. Usually you start your application like this: `java -cp ... com.package.ClassName` or the jar-version `java -jar jarName.jar` - the required classes will get loaded by the application class-loader or a parent. To load classes by a custom classloader, the class must not be loaded before by any parent classloader (else their definition is taken) and an explicit `loadClass(...)` statement – Roman Vottner Jan 27 '14 at 03:50
  • has to be made to the custom class-loader in order to tell him to load that class. 2) Well, the JVM needs to know what it actually has to execute - so the blueprint defines what actually needs to be executed when. – Roman Vottner Jan 27 '14 at 03:52
  • " In its current form the code won't even compile as the return value is missing " - why would a void method return something? Am I missing something here? – sofs1 Mar 21 '19 at 20:50
0

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

Hassen Ch.
  • 1,693
  • 18
  • 31
  • It's important to understand that `b` and `c` are *not* themselves object instances, but are *references* (pointers) to objects. Before the associated `new` operations execute they essentially hold a `null` value. – Hot Licks Jan 27 '14 at 01:31