Skip to content

Upgrade Java version to 25 on iteration 3#2

Open
moonct wants to merge 1 commit into
main-upgradefrom
main-upgrade-itr-3
Open

Upgrade Java version to 25 on iteration 3#2
moonct wants to merge 1 commit into
main-upgradefrom
main-upgrade-itr-3

Conversation

@moonct

@moonct moonct commented May 11, 2026

Copy link
Copy Markdown
Owner

Java Version Upgrade — Executive Report

Project: Bytecode Viewer 2.13.2 | Date: 2026-05-11 | Target: Java 25


1. 📋 Executive Summary

Bytecode Viewer, an open-source Java/Android reverse engineering suite, was successfully upgraded from Java 8 to Java 25 using an automated OpenRewrite migration pipeline combined with AI-assisted compilation fix-up via Amazon Kiro CLI. The automated tooling handled the bulk of the migration across 80+ source files in under 4 minutes. A post-migration compilation failure caused by unresolved OpenRewrite template placeholders was identified and fully resolved by Kiro, resulting in a clean build with zero compilation errors and all tests passing.


2. 🗂️ Application Changes

  • Application: Bytecode Viewer — a Swing-based desktop Java reverse engineering tool
  • Version: 2.13.2
  • Source files modified: 80+ Java source files across the full codebase
  • Build system: Maven (pom.xml updated to target Java 25)
  • Scope: Full codebase migration spanning GUI, decompilers, plugins, CLI, utilities, and resource handling layers

3. 🛠️ Tools Used

Tool Role
Java SDK 25 Target runtime and compiler
🔁 OpenRewrite 6.39.0 Automated source code migration recipe engine
📦 com.amazonaws.java.migrate.UpgradeToJava25 AWS-provided composite recipe orchestrating the full Java 8→25 upgrade path
🤖 Amazon Kiro CLI 2.0.1 AI agent used to diagnose and fix post-migration compilation errors
🏗️ Apache Maven 3.x Build, compile, test, and package

4. 🔧 Code Changes

Automated by OpenRewrite

  • pom.xml — Java version properties and maven-compiler-plugin updated to release 25
  • instanceof pattern matchingif (x instanceof Foo) { Foo f = (Foo) x; }if (x instanceof Foo f) across 15+ files (FileDrop, FieldCallSearch, MethodCallSearch, LDCSearch, ArrayParser, MethodCallParser, ConditionalParser, MyVoidVisitor, FieldAccessParser, ParserUtil, ClassViewer, TabComponent, GoToAction, ExtendedJOptionPane, ASMResourceUtil, and more)
  • Switch expressions — Traditional switch statements converted to switch expressions (HexViewer, InstructionPrinter, BytecodeViewPanelUpdater, ClassViewer)
  • String.formatted()String.format(...)"...".formatted(...) (FileHeaderUtils, MalwareCodeScanner, StackFramesRemover, PluginManager)
  • Text blocks — Multi-line string concatenations converted to """...""" (APKExport, JavaBytecodeTokenMaker, ClassViewer)
  • URL constructor → URI.create() — Deprecated new URL(...) replaced with URI.create(...).toURL() (PingBack, Boot, UpdateCheck)
  • Paths.get()Path.of() — (JRTExtractor, DirectoryResourceImporter)
  • SequencedCollection APIslist.get(0)list.getFirst(), list.get(list.size()-1)list.getLast() (MiscUtils, JRTExtractor, Settings, APKExport, ClassNodeDecompiler, MethodNodeDecompiler, FieldNodeDecompiler, MainViewerGUI, ResourceListIconRenderer, MyErrorStripe, GoToAction)
  • Unused variable _ — Unused lambda/catch parameters renamed to _ across 30+ files
  • @Serial annotation — Added to serialVersionUID fields in Swing components
  • System.outIO.println() — In applicable contexts across CLI and utility classes
  • Instance main methodpublic static void main(String[] args) modernized in BytecodeViewer and IconDemo
  • ClassLoader.defineClass — Migrated deprecated API in LibraryClassLoader
  • Extra semicolons removed — (BootState, CLIAction, ContextMenuType, DecompilerViewComponent, New, GoToBinaryPositionMode)

Manual fixes by Kiro CLI (post-OpenRewrite)

  • 🔨 InstructionPrinter.java — OpenRewrite left 16 broken __P__.<String>p() placeholders in a pattern-matching switch. Restored the original if-instanceof dispatch chain calling printVarInsnNode(), printIntInsnNode(), etc.
  • 🔨 AllatoriStringDecrypter.java — OpenRewrite replaced a complex 70-line if-instanceof block with broken placeholders. Fully restored the Allatori string decryption logic (LDC tracking, invokestatic detection, class loading, and InvokeDynamic handling).
  • 🔨 BytecodeViewPanelUpdater.java (×2) — yield __P__.nullp() placeholder in switch expression default branches replaced with yield null.
  • 🔨 ClassViewer.java (×1) — Same yield __P__.nullp() placeholder replaced with yield null.

5. ⏱️ Time Savings Estimate

Activity Manual Estimate Automated/AI
Reviewing and updating 80+ files for Java 25 idioms ~12–16 hours ~4 min (OpenRewrite)
Diagnosing broken placeholder syntax across 4 files ~1–2 hours ~5 min (Kiro CLI)
Restoring complex AllatoriStringDecrypter logic ~1 hour ~2 min (Kiro CLI)
Build verification and test runs ~30 min ~2 min (automated)
Total estimated savings ~15–20 hours ~13 min total

OpenRewrite itself estimated 12h 15m saved (logged in the build output). Kiro's fix-up work adds an additional ~2–3 hours of manual debugging avoided.


6. 🚀 Next Steps

Validation

  • 🧪 Run the full test suite in a CI environment with JDK 25 to catch any runtime regressions
  • 🖥️ Perform manual smoke testing of the GUI — load a JAR/APK, verify all 6 decompilers render output correctly
  • 🔍 Verify the Allatori String Decrypter plugin executes correctly end-to-end (the restored logic was complex)
  • 📦 Validate the packaged JAR launches correctly with java -jar on JDK 25

Improvement Recommendations

  • ⚠️ OpenRewrite placeholder bug — Report the __P__.<T>p() / __P__.nullp() unresolved template issue to the OpenRewrite project; these indicate the IfElseIfConstructToSwitch + SwitchCaseReturnsToSwitchExpression recipe chain fails silently on complex method bodies
  • 🔒 Pin the com.amazonaws.java.migrate.UpgradeToJava25 recipe version in rewrite.yml to ensure reproducible future runs
  • 🧹 Consider enabling --enable-preview in the Maven compiler config to access Java 25 preview features (value types, etc.) if needed in future iterations
  • 📊 Add a baseline set of unit tests for the decompiler output to catch regressions in future upgrades
  • 🔄 Schedule periodic OpenRewrite runs (e.g., quarterly) to keep the codebase current with new Java LTS idioms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant