What is heap pollution?

As mentioned earlier, arrays in Java are covariant. This means you can reference an object of type String[] through a variable of type Object[] and, for example, insert an Integer into it. Such code will compile, but when you try to store the value, an ArrayStoreException will be thrown.

Generics are protected by invariance. If you try to assign a List<String> value into a List<Object> variable, this type of error occurs already at compile time.

Heap pollution occurs when this protection fails, and a variable of a parameterized type holds an object parameterized with a different type. A simple example:

List<String> strings = (List) new ArrayList<Integer>();

The documentation guarantees that if the entire code is compiled together, heap pollution cannot happen without a compile-time warning.
Heap pollution can occur in two cases: when using arrays of generics and when mixing parameterized and raw types.

Raw types are parameterized types without specifying the parameter. An example with raw types that leads to heap pollution was already described above. Raw types should generally be avoided; the reasons are thoroughly explained in Chapter 26 of Effective Java. If information about generics is not needed, the wildcard (<?>) should be used instead.

The compiler does not allow the creation of arrays of parameterized types, as this would cause a "generic array creation" error. The illustration below shows what could happen in such cases.

A parameterized type of varargs argument of a method causes the same problem, as varargs are essentially array parameters. This is why it also triggers the "possible heap pollution" compiler warning. If you are sure there is no risk, starting from Java 7, this warning can be suppressed with the @SafeVarargs annotation.
What is heap pollution?