What is Heap Pollution?
Heap pollution implies that we have bad data in our heap memory. In Java language, heap pollution is a situation that occurs when a variable of parameterized type points to an object that is not of that parameterized type.How is Heap Pollution detected?
Usually, the compiler detects the heap pollution situation at the compile-time only and it throws unchecked warning message. At the run-time, there is a chance of arising heap pollution that will cause ClassCastException. Heap pollution means the bad data in the heap memory. Here bad data is an object of type X but an object of type Y is expected and it will throw ClassCastException at runtime. Lets understand the heap pollution with program:// Program to illustrate Heap pollution situation
import java.util.*;
class Geeks {
public static void main(String[] args)
{
// Creating a List of type String
List<String> listOfString = new ArrayList<>();
listOfString.add("Geeksforgeeks");
// Creating a List of type Integer which holds
// the reference of a List of type String
// Here compiler will detect that
// there is a chance of Heap pollution
// Compiler will throw an unchecked warning
// at the compile-time only
List<Integer> listOfInteger
= (List<Integer>)(Object)listOfString;
// Here we are trying to access
// firstElement of listOfInteger which holds
// the reference of a List of type String
// and trying to store it into
// one variable of type Integer
Integer firstElement
= listOfInteger.get(0);
System.out.println(firstElement);
}
}
prog.java:12: warning: [unchecked] unchecked cast
List listOfInteger = (List)(Object)listOfString;
^
required: List
found: Object
1 warning
Output:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at Geeks.main(File.java:16)
How to deal with Heap Pollution?
// Program to illustrate Heap pollution with respect to varargs
import java.util.*;
class Geeks {
public static void merge(List<String>... stringList)
{
// Here we are an array of type Object holds
// reference of an array of type List<String>
Object[] arr = stringList;
List<Integer> temp = new ArrayList<Integer>();
temp.add(420);
// Here we are trying to assign temp
// of type List<Integer> into arr[0]
// which is of type List<String>
// Here ClassCastException will be thrown
arr[0] = temp;
String firstEle = stringList[0].get(0);
System.out.println(firstEle);
}
// Driver code
public static void main(String args[])
{
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<String> list3 = new ArrayList<>();
list1.add("Geeks");
list2.add("for");
list3.add("geeks");
merge(list1, list2, list3);
}
}
Compile Time Console:
prog.java:4: warning:
[unchecked] Possible heap pollution from
parameterized vararg type List
public static void merge(List... stringList)
^
prog.java:23: warning:
[unchecked] unchecked generic array creation
for varargs parameter of type List[]
merge(list1, list2, list3);
^
2 warnings
Output:
Exception in thread "main" java.lang.ClassCastException:
java.lang.Integer cannot be cast to java.lang.String
at Geeks.merge(File.java:10)
at Geeks.main(File.java:23)
Note: If we don't want warnings at the compiler time then we can use @SafeVarargs annotation above the method. If we know that the method doesn't contain any heap pollution situation then you can annotate it with @SafeVarargs to suppress the warning. It does not mean that it will allow our code for heap pollution. It means that if in the code, there is a chance of Heap pollution, it will throw ClassCastException at the run time.
How to prevent Heap pollution situations?
We cant prevent Heap pollution situations, but we can follow a few rules that can help us to prevent heap pollution like: