Every non-constructor method that still has an ordinary bytecode body, anything left
over after nativization has taken what it can, is wrapped in a whole-method
catch (Throwable t) { throw t; }. This was chosen over more aggressive
decompiler-confusion techniques (malformed exception ranges, corrupted
attribute lengths) because it cannot change observable behaviour:
every path still terminates exactly as before, and an escaping exception still propagates
exactly as before. It only adds a control-flow shape, a handler covering an entire method
body with no locally-visible reason to exist, that common decompilers' control-flow-to-source
reconstruction tends to mishandle or render unreadably.
Applied once nativization decisions are already final, directly to whatever's left as
ordinary bytecode, never to a method about to be nativized, since a nativized method has no
Code attribute at all for a decompiler to see in the first place, and wrapping
it first would only add an unnecessary nested-exception-handler shape the translator doesn't
need to deal with.
This is a decompiler-output-quality attack, not a logic change and not a runtime protection: it doesn't detect anything or fail anything closed. It only makes the decompiled source of a non-nativized method harder to read correctly.
Class.forName across every output class, including those
no test exercises), with javap -v confirming a correctly typed
StackMapTable entry at each injected handler.