This is a famous fallacy (except in some very specific circumstances). The reason for the performance difference is probably due to packed structures and better CPU cache behavior.
Stack/heap makes very little difference in most circumstances for two reasons: first, Java heap allocation is as fast as stack allocation – it is a thread-local pointer bump. Deallocation for short-lived objects is free. You do incur an indirect cost of triggering a young-generation GC which causes a pause linearly related to the size of new-but-not-so-young objects. These pauses add up to very little (under 1% of total time). The second reason is that stack memory is usually a very small percentage of the total memory for interesting programs. Programs manipulate data. Non trivial programs usually manipulate lots of it, otherwise we wouldn't need so many gigabytes of RAM. A thread's stack is rarely over a few megabytes in size, so to have a significant portion of your data on stack you need tens of thousands of threads which the OS can't handle anyway.
To sum up: 1) Java's handling of short-lived memory is extremely fast; 2) all interesting data lives on the heap anyway.
Stack allocation can make a difference in reducing the number of young gen GCs, but it's not a huge difference in most circumstances. Packing your heap data structures better is more important.