Возможно, вам стоит посмотреть на проект Excelsior JET.
Он позволяет статически скомпилировать Java-приложение из байткода в оптимизированный нативный (машинный) код.
Иными словами, на входе подаете свое Java-приложение, на выходе получаете бинарник, как если бы вы скомпилировали бы какой-нибудь сишный код.
При этом, для работы скомпилированного приложения уже не нужны class-файлы (за исключением некоторых случаев), таким образом декомпилировать уже нечего.
Конечно, бинарник можно дизассемблировать и понять логику каких-нибудь локальных кусков, но восстановить из этого исходный код - это непосильная задача.
Собственно, прямых ссылок не буду давать, чтобы совсем не наглеть, учитывая, что я один из инженеров, работающих над этим проектом :)
Вместо этого дам ссылку на доклад моего коллеги на JavaZone на тему JET'а и AOT-компиляции Java-приложений в целом:
https://vimeo.com/181905276