From 3c22da5dc3b15f92ba9292ee01ccb77ce304114b Mon Sep 17 00:00:00 2001 From: vvb2060 Date: Mon, 20 Oct 2025 19:01:27 +0800 Subject: [PATCH] only cache offsets that require IO --- .../hiddenapibypass/HiddenApiBypassTest.java | 9 +-- .../org/lsposed/hiddenapibypass/Helper.java | 3 +- .../hiddenapibypass/HiddenApiBypass.java | 55 ++++++++++--------- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/library/src/androidTest/java/org/lsposed/hiddenapibypass/HiddenApiBypassTest.java b/library/src/androidTest/java/org/lsposed/hiddenapibypass/HiddenApiBypassTest.java index 699492f..90675b7 100644 --- a/library/src/androidTest/java/org/lsposed/hiddenapibypass/HiddenApiBypassTest.java +++ b/library/src/androidTest/java/org/lsposed/hiddenapibypass/HiddenApiBypassTest.java @@ -11,7 +11,6 @@ import android.content.pm.ApplicationInfo; import android.graphics.drawable.ClipDrawable; import android.os.Build; -import android.os.Process; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SdkSuppress; @@ -165,20 +164,14 @@ class X { public void PtestCachedOffset() { var context = InstrumentationRegistry.getInstrumentation().getContext(); var artVersion = Helper.getArtVersion(context); - var isOld = artVersion == -1L; var isNew = artVersion >= 36_00_00000L; - var is64bit = Process.is64Bit(); - var data = new long[10]; + var data = new long[6]; data[0] = 24; data[1] = 12; data[2] = 24; data[3] = 48; data[4] = 40; data[5] = isNew ? 40 : 56; - data[6] = isOld ? is64bit ? 40 : 28 : is64bit ? 32 : 24; - data[7] = is64bit ? 8 : 4; - data[8] = 16; - data[9] = 4; assertArrayEquals("art version " + artVersion, data, Helper.getCachedOffsetData()); } diff --git a/library/src/main/java/org/lsposed/hiddenapibypass/Helper.java b/library/src/main/java/org/lsposed/hiddenapibypass/Helper.java index c9ad934..3220fc2 100644 --- a/library/src/main/java/org/lsposed/hiddenapibypass/Helper.java +++ b/library/src/main/java/org/lsposed/hiddenapibypass/Helper.java @@ -49,7 +49,7 @@ public static long[] getCachedOffsetData() { } public static void setCachedOffsetData(long[] data) { - if (cachedOffsetData != null || data.length != 10) return; + if (cachedOffsetData != null || data.length != 6) return; cachedOffsetData = data; if (cacheFile == null) return; @@ -63,6 +63,7 @@ public static void setCachedOffsetData(long[] data) { } public static void enableOffsetCache(Context context) { + if (cacheFile != null) return; cacheFile = new File(context.getCacheDir(), "HiddenApiBypass"); artVersion = getArtVersion(context); diff --git a/library/src/main/java/org/lsposed/hiddenapibypass/HiddenApiBypass.java b/library/src/main/java/org/lsposed/hiddenapibypass/HiddenApiBypass.java index c131960..15be179 100644 --- a/library/src/main/java/org/lsposed/hiddenapibypass/HiddenApiBypass.java +++ b/library/src/main/java/org/lsposed/hiddenapibypass/HiddenApiBypass.java @@ -63,7 +63,7 @@ public final class HiddenApiBypass { unsafe = (Unsafe) Unsafe.class.getDeclaredMethod("getUnsafe").invoke(null); var data = Helper.getCachedOffsetData(); if (data == null) { - data = readOffsetData(); + data = readOffsetDataIO(); Helper.setCachedOffsetData(data); } else if (BuildConfig.DEBUG) { Log.d(TAG, "Using cached offset data"); @@ -74,18 +74,18 @@ public final class HiddenApiBypass { methodsOffset = data[3]; iFieldOffset = data[4]; sFieldOffset = data[5]; - artMethodSize = data[6]; - artMethodBias = data[7]; - artFieldSize = data[8]; - artFieldBias = data[9]; + var dataRT = readOffsetDataRT(); + artMethodSize = dataRT[0]; + artMethodBias = dataRT[1]; + artFieldSize = dataRT[2]; + artFieldBias = dataRT[3]; } catch (ReflectiveOperationException e) { Log.e(TAG, "Initialize error", e); throw new ExceptionInInitializerError(e); } - } - private static long[] readOffsetData() throws ReflectiveOperationException { + private static long[] readOffsetDataIO() throws ReflectiveOperationException { ClassLoader bootClassloader = new CoreOjClassLoader(); Class executableClass = bootClassloader.loadClass(Executable.class.getName()); Class methodHandleClass = bootClassloader.loadClass(MethodHandle.class.getName()); @@ -95,16 +95,27 @@ private static long[] readOffsetData() throws ReflectiveOperationException { var artOffset = unsafe.objectFieldOffset(methodHandleClass.getDeclaredField("artFieldOrMethod")); var methodsOffset = unsafe.objectFieldOffset(classClass.getDeclaredField("methods")); - long iField; - long sField; + long iFieldOffset; + long sFieldOffset; try { - iField = unsafe.objectFieldOffset(classClass.getDeclaredField("fields")); - sField = iField; + iFieldOffset = unsafe.objectFieldOffset(classClass.getDeclaredField("fields")); + sFieldOffset = iFieldOffset; } catch (NoSuchFieldException e) { - iField = unsafe.objectFieldOffset(classClass.getDeclaredField("iFields")); - sField = unsafe.objectFieldOffset(classClass.getDeclaredField("sFields")); + iFieldOffset = unsafe.objectFieldOffset(classClass.getDeclaredField("iFields")); + sFieldOffset = unsafe.objectFieldOffset(classClass.getDeclaredField("sFields")); } + long[] data = new long[6]; + data[0] = methodOffset; + data[1] = classOffset; + data[2] = artOffset; + data[3] = methodsOffset; + data[4] = iFieldOffset; + data[5] = sFieldOffset; + return data; + } + + private static long[] readOffsetDataRT() throws ReflectiveOperationException { Method mA = Helper.NeverCall.class.getDeclaredMethod("a"); Method mB = Helper.NeverCall.class.getDeclaredMethod("b"); mA.setAccessible(true); @@ -129,7 +140,7 @@ private static long[] readOffsetData() throws ReflectiveOperationException { MethodHandle mhJ = MethodHandles.lookup().unreflectGetter(fJ); long iAddr = unsafe.getLong(mhI, artOffset); long jAddr = unsafe.getLong(mhJ, artOffset); - long iFields = unsafe.getLong(Helper.NeverCall.class, iField); + long iFields = unsafe.getLong(Helper.NeverCall.class, iFieldOffset); var artFieldSize = jAddr - iAddr; if (BuildConfig.DEBUG) Log.v(TAG, artFieldSize + " " + Long.toString(iAddr, 16) + ", " + @@ -137,17 +148,11 @@ private static long[] readOffsetData() throws ReflectiveOperationException { Long.toString(iFields, 16)); var artFieldBias = iAddr - iFields; - long[] data = new long[10]; - data[0] = methodOffset; - data[1] = classOffset; - data[2] = artOffset; - data[3] = methodsOffset; - data[4] = iField; - data[5] = sField; - data[6] = artMethodSize; - data[7] = artMethodBias; - data[8] = artFieldSize; - data[9] = artFieldBias; + long[] data = new long[4]; + data[0] = artMethodSize; + data[1] = artMethodBias; + data[2] = artFieldSize; + data[3] = artFieldBias; return data; }