A simple way to get isolated heaps and message passing is multiple os processes and local sockets; this can be more heavy weight than threads/green threads though.
I've done some experimentation with hot reloading in c lately, and I'm not sure how isolated heaps is a precondition for code reloading.
I suspect the requirement for erlang style code reloading is a willingness to take an indirection penalty for fully qualified module calls and tail call optimization so that the old module doesn't stay in process stacks. In an OOP language, if you wanted to tie objects to specific versions of modules, you'd have to do some intrusive accounting as well.
I also attempted hot code reloading in perl many years ago; it's a lot easier to do when you've seen it done properly, and there are language facilities for it (fdlopen is a lot nicer to use than exec on a pm). In my use cases (which were single threaded), I was able to write an outside loop that's simple enough that it's not a big deal that it can't be reloaded.