Doppio uses JavaScript's garbage collector. (As a result, it cannot support weak references.) As for concurrency, thread quanta are mapped to JavaScript events, so Doppio can emulate preemptive multithreading. Doppio potentially preempts a "thread" at each function call.
The nitty gritty details are in the PLDI 2014 paper [0]. Some details have slightly changed, though (e.g. DoppioJVM supports JDK8 now).