Generics were bolted on in Java 5, and some painful compromises had to be made to have both backward compatibility and generics. The whole type erasure thing being the prime example.
There is some kind of heap corruption in that you can force a Duck in a list of Cars. But the very first time you try to use that Duck as a Car, the JVM will catch it and hit you with an exception. You won't get C-like undefined behavior this way.
Java had some painfull bugs with real world consequences. This is not one of them.
Now if you want to really abuse Java, try this one :
Field field = Integer.class.getDeclaredField("value");
field.setAccessible(true);
field.set(1, 666);
List<Integer> list = Arrays.asList(1, 2, 3);
System.out.println(list); //prints [666,2,3]
and java allows half of the number 1s in your program to magically change into a 666. Total mayhem ensues. Solution: Don't do this.