-
Notifications
You must be signed in to change notification settings - Fork 137
Memories
Stack memory is used when Java methods are called.
Each thread has its own stack.
The stack stores:
- Method calls
- Local variables
- Method parameters
- Primitive local values
- References to objects stored in heap memory
Stack memory is temporary.
When a method finishes, its stack frame is removed automatically.
Every method call creates a new stack frame.
Example:
public void calculateTotal() {
int quantity = 2;
double price = 150.00;
double total = quantity * price;
}When calculateTotal() runs, a stack frame is created.
The stack frame contains:
quantity = 2
price = 150.00
total = 300.00
When the method finishes, the stack frame is removed.
Example:
public void processBill() {
calculateTotal();
}
public void calculateTotal() {
double total = 500.00;
}Stack order:
processBill()
calculateTotal()
The most recently called method is removed first.
This is called:
Last In, First Out
or:
LIFO
Local variables are normally stored inside the current method's stack frame.
Example:
public void processPatient() {
int patientCount = 10;
boolean active = true;
}The variables patientCount and active exist only while processPatient() is running.
They cannot be used after the method finishes.
A local reference variable is stored in stack memory.
The actual object is stored in heap memory.
Example:
public void createPatient() {
Patient patient = new Patient();
}Memory idea:
Stack:
patient reference
|
v
Heap:
Patient object
The variable patient is in the stack frame.
The Patient object created with new Patient() is in heap memory.
Method parameters are stored in the method's stack frame.
Example:
public double calculateNetTotal(
double total,
double discount) {
return total - discount;
}The parameters total and discount are available only while the method is running.
Primitive local variables are stored directly in the stack frame.
Example:
public void calculate() {
int quantity = 5;
double price = 200.00;
boolean valid = true;
}The values are stored directly:
quantity = 5
price = 200.00
valid = true
public void processReport() {
int recordCount = 20;
String reportName = "Patient Report";
Department department = new Department();
}Memory idea:
Stack:
recordCount = 20
reportName reference
department reference
Heap:
"Patient Report" object
Department object
The local primitive recordCount is stored in the stack.
The local variables reportName and department store references.
Their objects are stored in heap memory.
Stack memory is limited.
A StackOverflowError may occur when methods call themselves continuously.
Example:
public void repeat() {
repeat();
}This method never stops calling itself.
Each call creates a new stack frame.
Eventually, the stack becomes full.
Result:
java.lang.StackOverflowError
Correct recursion must have a stopping condition.
public void countDown(int number) {
if (number <= 0) {
return;
}
countDown(number - 1);
}Each thread has its own stack.
Example:
Thread 1 → Stack 1
Thread 2 → Stack 2
Thread 3 → Stack 3
Local variables in one thread's stack are not directly shared with another thread.
However, stack references may point to the same object in heap memory.
A static member belongs to the class.
Example:
private static int patientCount;There is only one shared patientCount value for the class.
A static variable is not a local stack variable.
It is associated with the loaded class and is shared by all objects.
A static method can be called without creating an object.
public static boolean isValidAmount(double amount) {
return amount > 0;
}Call:
AmountValidator.isValidAmount(100.00);When the static method runs, its local variables and parameters are still stored in a stack frame.
Example:
public static boolean isValidAmount(double amount) {
boolean valid = amount > 0;
return valid;
}Here:
-
amountis in the method stack frame. -
validis in the method stack frame. - The method is static, but its local execution data still uses stack memory.
A non-static member belongs to an object.
Example:
private String patientName;Each object has its own patientName value.
Patient firstPatient = new Patient();
Patient secondPatient = new Patient();The two objects can store different names.
Non-static attributes are stored as part of their objects in heap memory.
When a non-static method runs, its local variables and parameters use stack memory.
Example:
public String formatPatientName() {
String formattedName = patientName.trim();
return formattedName;
}Here:
-
patientNamebelongs to the object in heap memory. -
formattedNameis a local variable in stack memory. - The current object reference, called
this, is available in the stack frame.
| Feature | Static | Non-static |
|---|---|---|
| Belongs to | Class | Object |
| Number of copies | One shared copy | One copy per object |
| Object required | No | Yes |
| Can access instance fields directly | No | Yes |
| Local variables during method call | Stack | Stack |
| Attribute storage | Shared class-associated storage | Inside object in heap |
public class PatientReport {
private static int generatedReportCount;
private String reportName;
private Department department;
public void generateReport() {
int resultCount = 25;
generatedReportCount++;
System.out.println(reportName);
System.out.println(resultCount);
}
public static int getGeneratedReportCount() {
return generatedReportCount;
}
}Memory idea:
Stack during generateReport():
resultCount = 25
this reference
Heap:
PatientReport object
reportName
department
Shared static data:
generatedReportCount
- Each thread has its own stack.
- Every method call creates a stack frame.
- Local variables are stored in the stack frame.
- Method parameters are stored in the stack frame.
- Local object variables store references in the stack.
- Actual objects are stored in heap memory.
- Stack data is removed when the method finishes.
- Static methods still use stack frames when they execute.
- Non-static attributes belong to objects in heap memory.
- Infinite recursion can cause
StackOverflowError.
Stack memory is mainly used for method execution.
It stores:
Method calls
Local variables
Parameters
Primitive local values
Object references
Example:
public void process() {
int count = 10;
Patient patient = new Patient();
}Memory idea:
Stack:
count = 10
patient reference
Heap:
Patient object
Heap memory is used to store Java objects and arrays.
Objects created using the new keyword are normally stored in heap memory.
Example:
Patient patient = new Patient();The Patient object is stored in heap memory.
The local reference variable patient is stored in the current method's stack frame.
Heap memory stores:
- Objects
- Object attributes
- Arrays
- Collections
- String objects
- Non-static attributes
- Shared objects referenced by different methods or threads
Example:
Patient patient = new Patient();
Department department = new Department();
List<Bill> bills = new ArrayList<>();The following objects are stored in heap memory:
Patient object
Department object
ArrayList object
Bill objects added to the list
Example:
Patient patient = new Patient();Memory idea:
Stack:
patient reference
|
v
Heap:
Patient object
The reference variable points to the object.
Non-static attributes belong to an object.
Example:
public class Patient {
private String patientCode;
private String patientName;
private boolean retired;
}When a Patient object is created:
Patient patient = new Patient();The object and its non-static attributes are stored in heap memory.
Memory idea:
Heap:
Patient object
patientCode
patientName
retired
Each object has its own values.
Patient firstPatient = new Patient();
Patient secondPatient = new Patient();Memory idea:
Heap:
Patient object 1
Patient object 2
The two objects can store different patient details.
Arrays are objects and are stored in heap memory.
Example:
int[] patientCounts = new int[5];Memory idea:
Stack:
patientCounts reference
|
v
Heap:
int array with 5 elements
Object array:
Patient[] patients = new Patient[3];The array object is stored in heap memory.
The array initially contains three null references.
Collection objects are stored in heap memory.
Example:
List<Patient> patients = new ArrayList<>();Memory idea:
Stack:
patients reference
|
v
Heap:
ArrayList object
When patient objects are added:
patients.add(new Patient());Both the ArrayList and the Patient object are in heap memory.
Strings are objects.
Example:
String patientName = "Kamal";The reference variable may be local to a method and stored in stack memory.
The string object is stored in heap memory.
String literals may be stored in the Java String Pool, which is part of heap memory.
Java automatically manages heap memory using garbage collection.
An object becomes eligible for garbage collection when no reachable reference points to it.
Example:
Patient patient = new Patient();
patient = null;After patient becomes null, the object may become eligible for garbage collection if no other reference points to it.
Garbage collection:
- Finds unreachable objects
- Releases heap memory
- Runs automatically
- Does not run at an exact time chosen by the programmer
Heap memory is limited.
If the application creates too many objects and memory cannot be released, Java may throw:
java.lang.OutOfMemoryError: Java heap space
Example problem:
List<Patient> patients = new ArrayList<>();
while (true) {
patients.add(new Patient());
}The list keeps references to every object.
Garbage collection cannot remove them because they are still reachable.
A memory leak happens when objects are no longer needed but are still referenced.
Example:
private static final List<Patient> patients =
new ArrayList<>();If the application continuously adds patients and never removes them:
patients.add(patient);the list can grow for the entire application lifetime.
This is especially dangerous because it is static and shared.
HMIS applications should not keep patient records in unnecessary long-lived static collections.
A static attribute belongs to the class.
Example:
private static int generatedReportCount;There is only one shared value for the class.
All objects use the same static value.
PatientReport firstReport = new PatientReport();
PatientReport secondReport = new PatientReport();Both objects share:
generatedReportCount
A static reference can point to an object in heap memory.
Example:
private static List<String> reportNames =
new ArrayList<>();The ArrayList object is in heap memory.
The static field keeps a shared reference to that object.
Because the static field may live as long as the class remains loaded, the object may also remain reachable for a long time.
A non-static attribute belongs to one object.
Example:
private String reportName;Every object has its own value.
PatientReport reportOne = new PatientReport();
PatientReport reportTwo = new PatientReport();Memory idea:
Heap:
PatientReport object 1
reportName
PatientReport object 2
reportName
Non-static attributes are stored as part of each object in heap memory.
| Feature | Static | Non-static |
|---|---|---|
| Belongs to | Class | Object |
| Number of copies | One shared copy | One copy per object |
| Object required | No | Yes |
| Shared between objects | Yes | No |
| Lifetime | Usually while class is loaded | While object is reachable |
| Can cause long-lived references | Yes | Less likely unless object is retained |
| Attribute data | Shared class-associated value | Stored inside each object |
A static method does not belong to an object.
Example:
public static Patient createPatient() {
return new Patient();
}The method itself does not create a permanent stack or heap area.
When the method runs:
- A stack frame is created.
-
new Patient()creates aPatientobject in heap memory. - The reference is returned.
Example:
Patient patient = PatientFactory.createPatient();Memory idea:
Stack:
patient reference
Heap:
Patient object
A non-static method belongs to an object.
Example:
public String getPatientName() {
return patientName;
}The object and its attribute patientName are in heap memory.
When the method runs:
- A stack frame is created.
- The current object reference
thisis available. - The method reads the object's heap data.
public class InvestigationReport {
private static int totalReportsGenerated;
private Department department;
private Investigation investigation;
private List<PatientInvestigation> results =
new ArrayList<>();
public void generateReport() {
totalReportsGenerated++;
results.add(new PatientInvestigation());
}
public static int getTotalReportsGenerated() {
return totalReportsGenerated;
}
}Memory idea:
Heap:
InvestigationReport object
department
investigation
results reference
ArrayList object
PatientInvestigation objects
Shared static data:
totalReportsGenerated
Example:
public void processPatient() {
int count = 1;
Patient patient = new Patient();
patient.setPatientCode("P001");
}Memory idea:
Stack:
count = 1
patient reference
Heap:
Patient object
patientCode = "P001"
The stack stores temporary method data.
The heap stores the object and its non-static attributes.
HMIS objects may contain sensitive data.
Examples:
private String patientName;
private String diagnosis;
private String investigationResult;Sensitive objects may remain in heap memory while they are reachable.
Avoid:
- Unnecessary static patient collections
- Long-lived references to patient data
- Caching sensitive values without a clear need
- Storing passwords as plain text
- Keeping large report results longer than required
Example of a risky static collection:
private static final List<Patient> allPatients =
new ArrayList<>();This collection may remain for the full application lifetime and prevent patient objects from being garbage collected.
- Remove references to objects that are no longer needed.
- Avoid unnecessary static collections.
- Clear large result lists when they are no longer required.
- Do not create objects repeatedly inside unnecessary loops.
- Use pagination for large reports.
- Avoid loading full entity graphs when a DTO is enough.
- Do not store sensitive patient data longer than necessary.
- Use appropriate bean scopes.
- Avoid memory leaks caused by long-lived references.
- Monitor heap usage in large HMIS reports.
- Objects are stored in heap memory.
- Arrays are stored in heap memory.
- Collections are stored in heap memory.
- Non-static attributes are stored inside objects.
- Static fields are shared by the class.
- A static reference can keep a heap object alive.
- Garbage collection removes unreachable objects.
- Too many reachable objects may cause
OutOfMemoryError. - Stack references can point to heap objects.
- Heap memory is shared between threads.
Heap memory stores Java objects and their non-static attributes.
Example:
Patient patient = new Patient();Memory idea:
Stack:
patient reference
Heap:
Patient object
Static and non-static difference:
Static:
One shared value belonging to the class.
Non-static:
One value per object stored as part of the object.
Main heap contents:
Objects
Arrays
Collections
String objects
Non-static attributes
Shared referenced data