- There's no way to do array access without null pointer and index checks each and every time.
- Generics with basic types, and their unfortunate embedding into syntax (like the new for() syntax), are awful. Boxing and unboxing incur a ludicrously high penalty, and generics push coders away from using arrays. Unlike in C++, generics have been the enemy of performance.
- Poor quality collections classes (ArrayList and HashMap are notoriously bad)
Sure there's a few other things like pointer walking etc. in C, and Java's poor floating point, but the big three above are the killers.