В случае с Java, я думаю, это в основном делается путем ограничения доступных библиотек. Поскольку в Java нет концепции указателя, и вы не можете загружать скомпилированный код (только байт-код JVM), вы не можете выйти из песочницы. Добавьте некоторое точное планирование процессов, и все готово!
Полагаю, самое сложное - это выбрать библиотеки, чтобы сделать их полезными, оставаясь в безопасности.
В случае с Python им пришлось модифицировать саму ВМ, потому что она не была разработана с учетом безопасности. К счастью, у них есть сам Гвидо, чтобы сделать это.