From f46c74193cc26294af8e274b3ac0f83acca1cabc Mon Sep 17 00:00:00 2001 From: liannacasper <67953602+liannacasper@users.noreply.github.com> Date: Tue, 14 Apr 2026 16:56:27 +0300 Subject: [PATCH 1/2] Fix concrete invoke dependency resolution when method context is unavailable --- .../codename1/tools/translator/bytecodes/CustomInvoke.java | 6 +++--- .../com/codename1/tools/translator/bytecodes/Invoke.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java index 2f3f74d296..8c835c654e 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java @@ -151,12 +151,12 @@ private String findActualOwner(ByteCodeClass bc) { } private String resolveConcreteInvokeOwner(ByteCodeClass ownerClass) { - if (ownerClass == null || ownerClass.getConcreteClass() == null || getMethod() == null) { + if (ownerClass == null || ownerClass.getConcreteClass() == null) { return null; } - String currentClass = getMethod().getClsName(); + String currentClass = getMethod() != null ? getMethod().getClsName() : null; String ownerName = ownerClass.getClsName(); - if (ownerName.equals(currentClass) || currentClass.startsWith(ownerName + "_")) { + if (currentClass != null && (ownerName.equals(currentClass) || currentClass.startsWith(ownerName + "_"))) { return null; } ByteCodeClass concreteClass = Parser.getClassObject(ownerClass.getConcreteClass().replace('/', '_').replace('$', '_')); diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/Invoke.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/Invoke.java index d3d8dcf251..767986f08e 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/Invoke.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/Invoke.java @@ -149,12 +149,12 @@ private String findActualOwner(ByteCodeClass bc) { } private String resolveConcreteInvokeOwner(ByteCodeClass ownerClass) { - if (ownerClass == null || ownerClass.getConcreteClass() == null || getMethod() == null) { + if (ownerClass == null || ownerClass.getConcreteClass() == null) { return null; } - String currentClass = getMethod().getClsName(); + String currentClass = getMethod() != null ? getMethod().getClsName() : null; String ownerName = ownerClass.getClsName(); - if (ownerName.equals(currentClass) || currentClass.startsWith(ownerName + "_")) { + if (currentClass != null && (ownerName.equals(currentClass) || currentClass.startsWith(ownerName + "_"))) { return null; } ByteCodeClass concreteClass = Parser.getClassObject(ownerClass.getConcreteClass().replace('/', '_').replace('$', '_')); From 8b099338e8b5c8d799d50c9935b1ec74538c1056 Mon Sep 17 00:00:00 2001 From: liannacasper <67953602+liannacasper@users.noreply.github.com> Date: Tue, 14 Apr 2026 17:21:45 +0300 Subject: [PATCH 2/2] Fix concrete invoke resolution regression without method context --- .../tools/translator/bytecodes/CustomInvoke.java | 11 +++++++---- .../codename1/tools/translator/bytecodes/Invoke.java | 9 ++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java index 8c835c654e..39c95edb08 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/CustomInvoke.java @@ -94,7 +94,7 @@ public void addDependencies(List dependencyList) { String dependencyOwner = owner; if (origOpcode == Opcodes.INVOKEVIRTUAL) { ByteCodeClass bc = Parser.getClassObject(owner.replace('/', '_').replace('$', '_')); - String resolvedConcreteOwner = resolveConcreteInvokeOwner(bc); + String resolvedConcreteOwner = resolveConcreteInvokeOwner(bc, true); if (resolvedConcreteOwner != null) { dependencyOwner = resolvedConcreteOwner; } @@ -150,11 +150,14 @@ private String findActualOwner(ByteCodeClass bc) { return findActualOwner(bc.getBaseClassObject()); } - private String resolveConcreteInvokeOwner(ByteCodeClass ownerClass) { + private String resolveConcreteInvokeOwner(ByteCodeClass ownerClass, boolean allowMissingMethodContext) { if (ownerClass == null || ownerClass.getConcreteClass() == null) { return null; } String currentClass = getMethod() != null ? getMethod().getClsName() : null; + if (currentClass == null && !allowMissingMethodContext) { + return null; + } String ownerName = ownerClass.getClsName(); if (currentClass != null && (ownerName.equals(currentClass) || currentClass.startsWith(ownerName + "_"))) { return null; @@ -209,7 +212,7 @@ public boolean appendExpression(StringBuilder b) { if (bc.isMethodPrivate(name, desc)) { isVirtual = false; } else { - String resolvedConcreteOwner = resolveConcreteInvokeOwner(bc); + String resolvedConcreteOwner = resolveConcreteInvokeOwner(bc, false); if (resolvedConcreteOwner != null) { invokeOwner = resolvedConcreteOwner; isVirtual = false; @@ -320,7 +323,7 @@ public void appendInstruction(StringBuilder b) { if (bc.isMethodPrivate(name, desc)) { isVirtual = false; } else { - String resolvedConcreteOwner = resolveConcreteInvokeOwner(bc); + String resolvedConcreteOwner = resolveConcreteInvokeOwner(bc, false); if (resolvedConcreteOwner != null) { invokeOwner = resolvedConcreteOwner; isVirtual = false; diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/Invoke.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/Invoke.java index 767986f08e..3309a7cc4b 100644 --- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/Invoke.java +++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/bytecodes/Invoke.java @@ -92,7 +92,7 @@ public void addDependencies(List dependencyList) { String dependencyOwner = owner; if (opcode == Opcodes.INVOKEVIRTUAL) { ByteCodeClass bc = Parser.getClassObject(owner.replace('/', '_').replace('$', '_')); - String resolvedConcreteOwner = resolveConcreteInvokeOwner(bc); + String resolvedConcreteOwner = resolveConcreteInvokeOwner(bc, true); if (resolvedConcreteOwner != null) { dependencyOwner = resolvedConcreteOwner; } @@ -148,11 +148,14 @@ private String findActualOwner(ByteCodeClass bc) { return findActualOwner(bc.getBaseClassObject()); } - private String resolveConcreteInvokeOwner(ByteCodeClass ownerClass) { + private String resolveConcreteInvokeOwner(ByteCodeClass ownerClass, boolean allowMissingMethodContext) { if (ownerClass == null || ownerClass.getConcreteClass() == null) { return null; } String currentClass = getMethod() != null ? getMethod().getClsName() : null; + if (currentClass == null && !allowMissingMethodContext) { + return null; + } String ownerName = ownerClass.getClsName(); if (currentClass != null && (ownerName.equals(currentClass) || currentClass.startsWith(ownerName + "_"))) { return null; @@ -194,7 +197,7 @@ public void appendInstruction(StringBuilder b) { if (bc.isMethodPrivate(name, desc)) { isVirtual = false; } else { - String resolvedConcreteOwner = resolveConcreteInvokeOwner(bc); + String resolvedConcreteOwner = resolveConcreteInvokeOwner(bc, false); if (resolvedConcreteOwner != null) { invokeOwner = resolvedConcreteOwner; isVirtual = false;