The world writeable cross thread also has implications on how your GC algorithm is designed.
Erlang for instance scopes gc pools per process so short lived processes just drop the pool. Also GC of one worker doesn't stop any others. Can't remember if it even needs to be generational because the heaps are already sliced by process. It's the closest thing to heap arenas I've seen in a VM based language.
Or take Lua which is single threaded and doesn't require VM safepoints since everything is done via cooperative coroutines.
Java needs to assume worst case and as such has to be conservative in some of it's approaches.