Understanding Java Inner Class Memory Leaks and How to Avoid Them
This article explains why non‑static inner classes in Java retain references to their outer class, causing memory leaks and eventual OutOfMemoryError, and demonstrates practical solutions such as avoiding references or converting the inner class to a static one, illustrated with code examples and debugging screenshots.
Introduction
The article discusses a common Java issue where improper use of inner classes leads to memory leaks and eventually memory overflow, providing guidance to help developers prevent this problem.
Why a non‑static inner class holding a reference to its outer class causes a memory leak
Non‑static inner classes implicitly hold a reference to the outer class instance (via the hidden this$0 field). If the inner class is retained elsewhere, the outer class cannot be garbage‑collected even when it is no longer needed.
Solutions
Do not let other parts of the code keep a reference to the non‑static inner class; execute business logic directly within the inner class.
Convert the non‑static inner class to a static inner class. A static inner class can only reference static members, so it cannot retain a reference to the outer instance.
Why hold a reference to the outer class?
Non‑static inner classes are useful when they need to access the outer class’s fields or methods, simplifying code by allowing direct use of outer members.
package org.example.a;
class Outer {
private String outerName = "Tony";
class Inner {
private String name;
public Inner() {
this.name = outerName;
}
}
Inner createInner() {
return new Inner();
}
}
public class Demo {
public static void main(String[] args) {
Outer.Inner inner = new Outer().createInner();
System.out.println(inner);
}
}When the inner class is static, the above code fails because the static inner class cannot access the non‑static field outerName:
package org.example.a;
class Outer {
private String outerName = "Tony";
static class Inner {
private String name;
public Inner() {
this.name = outerName; // compilation error
}
}
Inner createInner() {
return new Inner();
}
}Debugging insight
During debugging, the reference to the outer class is stored in a synthetic field named this$0.
Example without holding the outer class
package org.example.a;
class Outer {
static class Inner {
// no reference to Outer
}
Inner createInner() {
return new Inner();
}
}
public class Demo {
public static void main(String[] args) {
Outer.Inner inner = new Outer().createInner();
System.out.println(inner);
}
}Running this version shows that the inner class no longer retains the outer instance.
Memory leak demonstration
package org.example.a;
import java.util.ArrayList;
import java.util.List;
class Outer {
private int[] data;
public Outer(int size) {
this.data = new int[size];
}
class Inner {}
Inner createInner() { return new Inner(); }
}
public class Demo {
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
int counter = 0;
while (true) {
list.add(new Outer(100000).createInner());
System.out.println(counter++);
}
}
}This loop quickly exhausts heap memory because each Inner instance keeps its Outer instance (which holds a large array) alive.
Solution that avoids the leak
package org.example.a;
import java.util.ArrayList;
import java.util.List;
class Outer {
private int[] data;
public Outer(int size) { this.data = new int[size]; }
static class Inner {}
Inner createInner() { return new Inner(); }
}
public class Demo {
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
int counter = 0;
while (true) {
list.add(new Outer(100000).createInner());
System.out.println(counter++);
}
}
}Because Inner is static, it no longer holds a reference to Outer, and the program can run for hundreds of thousands of iterations without running out of memory.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
