From 86ea17af034f0c50aa0e5e9f19143fc1ca1f0cc5 Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Fri, 13 Feb 2026 16:30:57 +0100 Subject: [PATCH] Implement constructor invocation APIs in LSPosedContext Unlike the existing `newInstance` variants which allocate and return a new object, these new APIs execute constructor logic on an existing, pre-allocated instance (`thisObject`). This separation of allocation and initialization allows for invoking original or super constructors within hook callbacks where the object reference is already established. The implementation leverages the existing JNI `HookBridge` methods, as `invokeOriginalMethod` and `invokeSpecialMethod` already support void-return signatures required for constructor execution. --- .../java/org/lsposed/lspd/impl/LSPosedContext.java | 13 ++++++++++++- xposed/libxposed | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java b/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java index 3fde28020..9551bbac7 100644 --- a/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java +++ b/core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java @@ -210,10 +210,16 @@ public boolean deoptimize(@NonNull Constructor constructor) { @Nullable @Override - public Object invokeOrigin(@NonNull Method method, @Nullable Object thisObject, Object[] args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException { + public Object invokeOrigin(@NonNull Method method, @Nullable Object thisObject, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException { return HookBridge.invokeOriginalMethod(method, thisObject, args); } + @Override + public void invokeOrigin(@NonNull Constructor constructor, @NonNull T thisObject, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException { + // The bridge returns an Object (null for void/constructors), which we discard. + HookBridge.invokeOriginalMethod(constructor, thisObject, args); + } + private static char getTypeShorty(Class type) { if (type == int.class) { return 'I'; @@ -257,6 +263,11 @@ public Object invokeSpecial(@NonNull Method method, @NonNull Object thisObject, return HookBridge.invokeSpecialMethod(method, getExecutableShorty(method), method.getDeclaringClass(), thisObject, args); } + @Override + public void invokeSpecial(@NonNull Constructor constructor, @NonNull T thisObject, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException { + HookBridge.invokeSpecialMethod(constructor, getExecutableShorty(constructor), constructor.getDeclaringClass(), thisObject, args); + } + @NonNull @Override public T newInstanceOrigin(@NonNull Constructor constructor, Object... args) throws InvocationTargetException, IllegalAccessException, InstantiationException { diff --git a/xposed/libxposed b/xposed/libxposed index 545827303..55efdf9d1 160000 --- a/xposed/libxposed +++ b/xposed/libxposed @@ -1 +1 @@ -Subproject commit 54582730315ba4a3d7cfaf9baf9d23c419e07006 +Subproject commit 55efdf9d159195261d7326e9e125965a90025a12