Glossary

What is code obfuscation

Code obfuscation makes an app's compiled code hard to read without changing behaviour. What it reaches per language, what it can break and how to validate it.

Code obfuscation transforms an app’s compiled code so that it keeps working exactly as before but becomes far harder for a person or a decompiler to understand. It renames identifiers, hides strings and reshapes logic without changing behaviour. What it can reach depends on the language: Java and Kotlin bytecode, Swift and Objective-C machine code, C and C++ libraries, compiled Dart and JavaScript bundles each reveal different things. Obfuscation slows reverse engineering and protects the checks placed around it. It does not hide traffic the app sends over the network, and secrets that belong on a server should stay there.

What obfuscation acts on

CodeHow it shipsWhat an analyst sees without protection
Kotlin and Java (Android)DEX bytecode in the APK or app bundleClass, method and field names; output that reads close to source
Swift (iOS)Native machine code in the app binaryType metadata and names the Swift runtime keeps
Objective-C (iOS)Native machine code with runtime metadataEvery class and selector name
C and C++ (both)Shared librariesExported symbols and plain strings
Dart (Flutter)Ahead-of-time compiled native libraryFunction and class names unless renamed
JavaScript (React Native)Text bundle or Hermes bytecodeReadable logic after unpacking

Platform tooling offers a baseline. R8 renames and shrinks Java and Kotlin code, and Flutter’s obfuscate build option renames Dart symbols. Strings, control flow and native code stay readable under both, and on iOS the standard build strips symbols but does not rename Swift or Objective-C names.

Compatibility: what can break

Obfuscation changes names, and some code looks names up at runtime. Test each of these before release:

  • Reflection. Code that finds a class or method by its name string, common in Android libraries.
  • Serialisation. JSON and database mappers that derive keys from field names.
  • Selectors and key-value coding. Objective-C calls resolved by name, and Swift members exposed to the Objective-C runtime.
  • Plugins and bridges. Flutter platform channels and React Native native modules that match names across the language boundary.
  • Dependency injection and third-party SDKs. Frameworks that expect their own class names to survive.
  • Crash symbolication. Android traces need the mapping file, iOS traces need the dSYM, and Flutter traces need the split debug information.

Each item needs either a keep rule or a test that proves the renamed path still works.

Validation: proving it worked

Good obfuscation is measured, not assumed. Pick the classes and strings that matter, decompile the protected and unprotected builds, and compare what an analyst can recover. Run your regression suite and the journeys users rely on. Measure launch time and package size on real devices. Trigger a test crash and confirm the trace translates back to readable code. Record the results per release so a later build that drops a rule is noticed.

How Otukan applies obfuscation

Otukan obfuscates identifiers, strings, control flow, resources and native libraries, and protects Dart and JavaScript or Hermes code directly. A maintained keep list covers reflection, serialisation and SDK names. You choose where heavier transforms run, and every protected build ships with a private mapping for crash analysis. Obfuscation also hides Otukan’s own integrity and runtime checks, and Otukan validates each release with you through decompiler comparison, a test crash and measured journeys on your devices, inside your existing build pipeline, with your signing keys staying yours.

The product control is covered on mobile code obfuscation. SDK providers protecting their own code inside other companies’ apps can read protecting an SDK you distribute. For the wider protection set, see what is app shielding. Related terms are in the mobile security glossary.

Common questions

  • Is the obfuscation built into Android and Flutter enough?

    It is a useful baseline. R8 renames and shrinks Java and Kotlin code on Android, and Flutter's obfuscate build option renames Dart symbols. Neither hides strings, restructures control flow or protects native libraries, so endpoints, keys and algorithms stay easy to find. Apps that handle money, identity or valuable logic usually need stronger transforms on top.

  • Does obfuscation slow the app down?

    Renaming has little runtime effect. String protection and control-flow transforms do cost something, because the code does more work to reach the same result. The sensible approach is to apply the heavier transforms only to the code that deserves them and to measure launch time and key journeys on your own devices before release.

  • Can obfuscated code still be reverse engineered?

    Given enough time, a skilled analyst can study any code that runs on a device they control. Obfuscation raises the time and skill required, protects the runtime checks around it from being found easily, and turns a quick read into a long project. That is its value: attacks become slower, costlier and less repeatable.

Keep your logic yours

Tell us the platforms, the languages and frameworks in your app and which logic or data you most want to keep private. We do not ask for source code, binaries, signing keys or production credentials.

Or request a technical demo