Native breakpoints make it easy to implement "runtime" breakpoints, i.e. setting breakpoints when the debuggee is in execution.
Moreover, since the bytecodes are translated to native code on a per Method basis, it will not be possible to set a breakpoint in the current method with the bytecode mechanism.
JVMDI specification has APIs to put breakpoints at a given bytecode index. In CISC architectures, a single native instruction could subsume many bytecode entries, which makes it impossible to stop the debugger at a particular index. In other words, single stepping through the bytecode becomes difficult.
Using NSPR threads might add a runtime overhead associated with thread scheduling. The alternative would be to use an event driven model, where the VM responds to asynchronous debugger events. But using NSPR threads seems to be the most portable way of doing it.