diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java index 3f4b99d63711..c1d822451ae9 100644 --- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java +++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java @@ -1393,10 +1393,29 @@ private List getDefaultPackages(@NonNull PackageManagerLocal.FilteredSna @NonNull /* @BatchDexoptReason|REASON_INACTIVE */ String reason) { var appHibernationManager = mInjector.getAppHibernationManager(); - // Filter out hibernating packages even if the reason is REASON_INACTIVE. This is because - // artifacts for hibernating packages are already deleted. - Stream packages = snapshot.getPackageStates().values().stream().filter( - pkgState -> Utils.canDexoptPackage(pkgState, appHibernationManager)); + Stream packages = snapshot.getPackageStates().values().stream().filter(pkgState -> { + // Filter out hibernating packages even if the reason is REASON_INACTIVE. This is because + // artifacts for hibernating packages are already deleted. + if (!Utils.canDexoptPackage(pkgState, appHibernationManager)) { + return false; + } + + if (reason.equals(ReasonMapping.REASON_PRE_REBOOT_DEXOPT)) { + // pre-reboot dexopt runs ART code from next OTA update, it doesn't have access to + // system_server code that is called below + return true; + } + + List statuses = getDexoptStatus(snapshot, pkgState.getPackageName()) + .getDexContainerFileDexoptStatuses(); + + for (var s : statuses) { + if (!"speed".equals(s.getCompilerFilter())) { + return true; + } + } + return false; + }); switch (reason) { case ReasonMapping.REASON_BOOT_AFTER_MAINLINE_UPDATE: diff --git a/libartservice/service/java/com/android/server/art/BackgroundDexoptJob.java b/libartservice/service/java/com/android/server/art/BackgroundDexoptJob.java index 330940f9d530..4f939d2cf070 100644 --- a/libartservice/service/java/com/android/server/art/BackgroundDexoptJob.java +++ b/libartservice/service/java/com/android/server/art/BackgroundDexoptJob.java @@ -127,6 +127,18 @@ public boolean onStopJob(@NonNull JobParameters params) { throw new IllegalStateException("This job cannot be scheduled"); } + start().thenAcceptAsync(result -> { + Map dr = null; + long durationMs = 0L; + if (result instanceof CompletedResult r) { + dr = r.dexoptResultByPass(); + for (Long v : r.durationMsByPass().values()) { + durationMs += v.longValue(); + } + } + mInjector.getPackageManagerLocal().onBgDexoptCompleted(dr, durationMs); + }); + if (SystemProperties.getBoolean("pm.dexopt.disable_bg_dexopt", false /* def */)) { AsLog.i("Job is disabled by system property 'pm.dexopt.disable_bg_dexopt'"); return ArtFlags.SCHEDULE_DISABLED_BY_SYSPROP; diff --git a/libartservice/service/java/com/android/server/art/DexoptHelper.java b/libartservice/service/java/com/android/server/art/DexoptHelper.java index b5f02ae5e751..04b68319be19 100644 --- a/libartservice/service/java/com/android/server/art/DexoptHelper.java +++ b/libartservice/service/java/com/android/server/art/DexoptHelper.java @@ -53,6 +53,7 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.function.Function; @@ -115,7 +116,7 @@ public DexoptResult dexopt(@NonNull PackageManagerLocal.FilteredSnapshot snapsho private DexoptResult dexoptPackages(@NonNull List pkgStates, @NonNull DexoptParams params, @NonNull CancellationSignal cancellationSignal, @NonNull Executor dexoptExecutor, @Nullable Executor progressCallbackExecutor, - @Nullable Consumer progressCallback) { + @Nullable Consumer origProgressCallback) { // TODO(jiakaiz): Find out whether this is still needed. long identityToken = Binder.clearCallingIdentity(); @@ -154,7 +155,19 @@ private DexoptResult dexoptPackages(@NonNull List pkgStates, }, dexoptExecutor)); } + Consumer progressCallback = + DexoptHooks.maybeWrapDexoptProgressCallback(params, origProgressCallback); + if (progressCallback != null) { + if (progressCallbackExecutor == null) { + if (origProgressCallback == progressCallback) { + // this is not a wrapper progress callback, and caller hasn't supplied the + // executor + throw new NullPointerException("progressCallbackExecutor"); + } + progressCallbackExecutor = Executors.newSingleThreadExecutor(); + } + CompletableFuture.runAsync(() -> { progressCallback.accept(OperationProgress.create( 0 /* current */, futures.size(), null /* packageDexoptResult */)); diff --git a/libartservice/service/java/com/android/server/art/DexoptHooks.java b/libartservice/service/java/com/android/server/art/DexoptHooks.java new file mode 100644 index 000000000000..96f4943b3b87 --- /dev/null +++ b/libartservice/service/java/com/android/server/art/DexoptHooks.java @@ -0,0 +1,56 @@ +package com.android.server.art; + +import android.annotation.Nullable; +import android.os.SystemClock; +import android.util.Slog; + +import com.android.server.LocalManagerRegistry; +import com.android.server.art.model.DexoptParams; +import com.android.server.art.model.OperationProgress; +import com.android.server.pm.PackageManagerLocal; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; + +class DexoptHooks { + static final String TAG = DexoptHooks.class.getSimpleName(); + + static AtomicBoolean shouldWrapBgDexoptProgressCallback = new AtomicBoolean(true); + + @Nullable + static Consumer maybeWrapDexoptProgressCallback( + DexoptParams params, @Nullable Consumer orig) { + + switch (params.getReason()) { + case ReasonMapping.REASON_BG_DEXOPT: + if (shouldWrapBgDexoptProgressCallback.getAndSet(false)) { + break; + } + return orig; + default: + return orig; + } + + final long start = SystemClock.elapsedRealtime(); + + var pm = Objects.requireNonNull(LocalManagerRegistry.getManager(PackageManagerLocal.class)); + + Consumer res = progress -> { + if (orig != null) { + orig.accept(progress); + } + + String reason = params.getReason(); + + Slog.d(TAG, "onDexoptProgress: reason " + reason + ", " + progress); + + switch (reason) { + case ReasonMapping.REASON_BG_DEXOPT -> + pm.onBgDexoptProgressUpdate(start, progress.getPercentage(), progress.getCurrent(), progress.getTotal()); + } + }; + + return res; + } +} diff --git a/libartservice/service/java/com/android/server/art/Dexopter.java b/libartservice/service/java/com/android/server/art/Dexopter.java index 2c46598052ab..ac40c0b9854d 100644 --- a/libartservice/service/java/com/android/server/art/Dexopter.java +++ b/libartservice/service/java/com/android/server/art/Dexopter.java @@ -382,18 +382,11 @@ public final List dexopt() throws RemoteException @NonNull private String adjustCompilerFilter( @NonNull String targetCompilerFilter, @NonNull DexInfoType dexInfo) { - if ((mParams.getFlags() & ArtFlags.FLAG_FORCE_COMPILER_FILTER) == 0) { - if (mInjector.isSystemUiPackage(mPkgState.getPackageName())) { - String systemUiCompilerFilter = getSystemUiCompilerFilter(); - if (!systemUiCompilerFilter.isEmpty()) { - targetCompilerFilter = printAdjustCompilerFilterReason(targetCompilerFilter, - systemUiCompilerFilter, "the package is System UI"); - } - } else if (mInjector.isLauncherPackage(mPkgState.getPackageName())) { - targetCompilerFilter = printAdjustCompilerFilterReason( - targetCompilerFilter, "speed-profile", "the package is a launcher package"); - } + if (mPkgState.isSystem()) { + targetCompilerFilter = "speed"; + } + if ((mParams.getFlags() & ArtFlags.FLAG_FORCE_COMPILER_FILTER) == 0) { Callback callback = mInjector.getConfig().getAdjustCompilerFilterCallback(); if (callback != null) { @@ -447,6 +440,17 @@ private String adjustCompilerFilter( targetCompilerFilter, "verify", "the user requests to ignore the profile"); } + // pre-reboot dexopt runs ART code from next OTA update, it doesn't have access to + // system_server code + if (!ReasonMapping.REASON_PRE_REBOOT_DEXOPT.equals(mParams.getReason())) { + String override = mInjector.getPackageManagerLocal() + .maybeOverrideCompilerFilter(targetCompilerFilter, mPkg, mParams); + + if (override != null) { + return override; + } + } + return targetCompilerFilter; } diff --git a/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java b/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java index 093ea40ec76a..342787cd213f 100644 --- a/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java +++ b/libartservice/service/java/com/android/server/art/PreRebootDexoptJob.java @@ -585,11 +585,7 @@ private boolean isEnabled() { } public boolean isAsyncForOta() { - if (android.os.Flags.updateEngineApi()) { - return true; - } - // Legacy flag in Android V. - return SystemProperties.getBoolean("dalvik.vm.pr_dexopt_async_for_ota", false /* def */); + return false; } @GuardedBy("this") diff --git a/libartservice/service/java/com/android/server/art/ReasonMapping.java b/libartservice/service/java/com/android/server/art/ReasonMapping.java index e6296e02de24..44321187f2f0 100644 --- a/libartservice/service/java/com/android/server/art/ReasonMapping.java +++ b/libartservice/service/java/com/android/server/art/ReasonMapping.java @@ -137,6 +137,10 @@ private ReasonMapping() {} */ @NonNull public static String getCompilerFilterForReason(@NonNull String reason) { + if (REASON_PRE_REBOOT_DEXOPT.equals(reason)) { + return "speed-profile"; + } + String value = SystemProperties.get("pm.dexopt." + reason); if (TextUtils.isEmpty(value)) { throw new IllegalArgumentException("No compiler filter for reason '" + reason + "'"); @@ -209,6 +213,10 @@ public static String getCompilerFilterForShared() { * @hide */ public static int getConcurrencyForReason(@NonNull @BatchDexoptReason String reason) { + if (REASON_BG_DEXOPT.equals(reason) || REASON_PRE_REBOOT_DEXOPT.equals(reason)) { + return SystemProperties.getInt("pm.dexopt." + reason + ".concurrency", 2 /* def */); + } + // TODO(jiakaiz): Revisit the concurrency for non-boot reasons. return SystemProperties.getInt("pm.dexopt." + reason + ".concurrency", BOOT_REASONS.contains(reason) ? 4 : 1 /* def */); diff --git a/runtime/Android.bp b/runtime/Android.bp index edd63e56f75e..0c27eef0cbab 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -44,6 +44,37 @@ cc_defaults { "-Wno-unused-command-line-argument", ], }, + android_arm: { + // Arm 32 bit does not produce complete exidx unwind information + // so keep the .debug_frame which is relatively small and does + // include needed unwind information. + // See b/132992102 and b/145790995 for details. + strip: { + keep_symbols_and_debug_frame: true, + }, + }, + // For all other architectures, leave the symbols in the shared library + // so that stack unwinders can produce meaningful name resolution. + android_arm64: { + strip: { + keep_symbols: true, + }, + }, + android_riscv64: { + strip: { + keep_symbols: true, + }, + }, + android_x86: { + strip: { + keep_symbols: true, + }, + }, + android_x86_64: { + strip: { + keep_symbols: true, + }, + }, }, } diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc index 0474361f1cab..45755065e2da 100644 --- a/runtime/hidden_api.cc +++ b/runtime/hidden_api.cc @@ -170,6 +170,11 @@ static Domain DetermineDomainFromLocation(const std::string& dex_location, } } + if (dex_location == "/system/app/GmsCompatLib/GmsCompatLib.apk" || + (dex_location.starts_with("/data/app/~~") && dex_location.find("==/app.grapheneos.gmscompat.lib-") != std::string::npos)) { + return Domain::kPlatform; + } + if (LocationIsOnSystemFramework(dex_location)) { return Domain::kPlatform; } diff --git a/runtime/jit/profile_saver_options.h b/runtime/jit/profile_saver_options.h index 707ebf480a94..37f29cb4ce54 100644 --- a/runtime/jit/profile_saver_options.h +++ b/runtime/jit/profile_saver_options.h @@ -71,7 +71,7 @@ struct ProfileSaverOptions { wait_for_jit_notifications_to_save_(wait_for_jit_notifications_to_save) {} bool IsEnabled() const { - return enabled_; + return false; } void SetEnabled(bool enabled) { enabled_ = enabled; diff --git a/runtime/native/dalvik_system_BaseDexClassLoader.cc b/runtime/native/dalvik_system_BaseDexClassLoader.cc index f9a1aba022e6..dc738582d12b 100644 --- a/runtime/native/dalvik_system_BaseDexClassLoader.cc +++ b/runtime/native/dalvik_system_BaseDexClassLoader.cc @@ -69,7 +69,7 @@ static jobjectArray BaseDexClassLoader_computeClassLoaderContextsNative(JNIEnv* return soa.AddLocalReference(array.Get()); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { NATIVE_METHOD(BaseDexClassLoader, computeClassLoaderContextsNative, "()[Ljava/lang/String;"), }; diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index da5fe5f0f2e5..dbb44eaeee4c 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -62,6 +62,8 @@ #include #endif // ART_TARGET_ANDROID +#include + namespace art HIDDEN { // Should be the same as dalvik.system.DexFile.ENFORCE_READ_ONLY_JAVA_DCL @@ -178,6 +180,17 @@ class NullableScopedUtfChars { void operator=(const NullableScopedUtfChars&); }; + +#define FLAG_RESTRICT_MEMORY_DCL 1 +#define FLAG_RESTRICT_STORAGE_DCL (1 << 1) + +#define MAX_PAGE_SIZE (16 * 1024) + +static union { + int dynCodeLoadingFlags = 0; + char padding[MAX_PAGE_SIZE]; +} ro __attribute__((aligned(MAX_PAGE_SIZE))); + static jobject CreateCookieFromOatFileManagerResult( JNIEnv* env, std::vector>& dex_files, @@ -209,6 +222,14 @@ static jobject CreateCookieFromOatFileManagerResult( return array; } +static void DexFile_enableDynCodeLoadingChecks(JNIEnv*, jclass, int flags) { + ro.dynCodeLoadingFlags |= flags; // use |= to make flags harder to clear + if (mprotect(&ro, sizeof(ro), PROT_READ) != 0) { + LOG(ERROR) << "unable to mprotect ro: " << strerror(errno); + exit(1); + } +} + static MemMap AllocateDexMemoryMap(JNIEnv* env, jint start, jint end) { if (end <= start) { ScopedObjectAccess soa(env); @@ -258,6 +279,16 @@ static jobject DexFile_openInMemoryDexFilesNative(JNIEnv* env, jintArray jends, jobject class_loader, jobjectArray dex_elements) { + + if (ro.dynCodeLoadingFlags & FLAG_RESTRICT_MEMORY_DCL) { + ScopedLocalRef cls(env, env->FindClass("android/ext/dcl/DynCodeLoading")); + jmethodID method = env->GetStaticMethodID(cls.get(), "checkInMemoryDexFileOpen", "(I)V"); + env->CallStaticVoidMethod(cls.get(), method, (jint) ro.dynCodeLoadingFlags); + if (env->ExceptionCheck()) { + return nullptr; + } + } + jsize buffers_length = env->GetArrayLength(buffers); CHECK_EQ(buffers_length, env->GetArrayLength(arrays)); CHECK_EQ(buffers_length, env->GetArrayLength(jstarts)); @@ -377,6 +408,15 @@ static jobject DexFile_openDexFileNative(JNIEnv* env, return nullptr; } + if (ro.dynCodeLoadingFlags & FLAG_RESTRICT_STORAGE_DCL) { + ScopedLocalRef cls(env, env->FindClass("android/ext/dcl/DynCodeLoading")); + jmethodID method = env->GetStaticMethodID(cls.get(), "checkDexFileOpen", "(ILjava/lang/String;)V"); + env->CallStaticVoidMethod(cls.get(), method, (jint) ro.dynCodeLoadingFlags, javaSourceName); + if (env->ExceptionCheck()) { + return nullptr; + } + } + if (isReadOnlyJavaDclChecked() && access(sourceName.c_str(), W_OK) == 0) { LOG(ERROR) << "Attempt to load writable dex file: " << sourceName.c_str(); if (isReadOnlyJavaDclEnforced(env)) { @@ -961,7 +1001,8 @@ static void DexFile_setTrusted(JNIEnv* env, jclass, jobject j_cookie) { } } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { + NATIVE_METHOD(DexFile, enableDynCodeLoadingChecks, "(I)V"), NATIVE_METHOD(DexFile, closeDexFile, "(Ljava/lang/Object;)Z"), NATIVE_METHOD(DexFile, defineClassNative, diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc index c3be52106c81..93ce00a2cd4d 100644 --- a/runtime/native/dalvik_system_VMDebug.cc +++ b/runtime/native/dalvik_system_VMDebug.cc @@ -671,7 +671,7 @@ static void VMDebug_setUserId(JNIEnv* env, jclass, jint user_id) { Runtime::Current()->GetRuntimeCallbacks()->SetUserId(user_id); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { NATIVE_METHOD(VMDebug, countInstancesOfClass, "(Ljava/lang/Class;Z)J"), NATIVE_METHOD(VMDebug, countInstancesOfClasses, "([Ljava/lang/Class;Z)[J"), NATIVE_METHOD(VMDebug, dumpHprofData, "(Ljava/lang/String;I)V"), diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 769e98185222..7692f247b8e7 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -554,7 +554,7 @@ static jboolean VMRuntime_isArtTestRwFlagEnabled([[maybe_unused]] JNIEnv* env, return is_test_rw_flag_enabled(); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(VMRuntime, addressOf, "(Ljava/lang/Object;)J"), NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"), NATIVE_METHOD(VMRuntime, clampGrowthLimit, "()V"), diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc index f55e2b5c18f7..3491d38bb24b 100644 --- a/runtime/native/dalvik_system_VMStack.cc +++ b/runtime/native/dalvik_system_VMStack.cc @@ -161,7 +161,7 @@ static jobjectArray VMStack_getAnnotatedThreadStackTrace(JNIEnv* env, jclass, jo return GetThreadStack(soa, javaThread, fn); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(VMStack, fillStackTraceElements, "(Ljava/lang/Thread;[Ljava/lang/StackTraceElement;)I"), FAST_NATIVE_METHOD(VMStack, getCallingClassLoader, "()Ljava/lang/ClassLoader;"), FAST_NATIVE_METHOD(VMStack, getClosestUserClassLoader, "()Ljava/lang/ClassLoader;"), diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index 3af197866bf1..abf8e8a847bf 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -466,7 +466,7 @@ static jboolean ZygoteHooks_nativeZygoteLongSuspendOk([[maybe_unused]] JNIEnv* e return (isJitZygote || explicitlyDisabled) ? JNI_FALSE : JNI_TRUE; } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { NATIVE_METHOD(ZygoteHooks, nativePreFork, "()J"), NATIVE_METHOD(ZygoteHooks, nativePostZygoteFork, "()V"), NATIVE_METHOD(ZygoteHooks, nativePostForkSystemServer, "(I)V"), diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 9a4bda85d362..b134f7c8557e 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -967,7 +967,7 @@ static jobject Class_newInstance(JNIEnv* env, jobject javaThis) { return soa.AddLocalReference(receiver.Get()); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Class, classForName, "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"), FAST_NATIVE_METHOD(Class, ensureExtDataPresent, "()Ldalvik/system/ClassExt;"), diff --git a/runtime/native/java_lang_Object.cc b/runtime/native/java_lang_Object.cc index 5649b2cc5ba1..d3288279851b 100644 --- a/runtime/native/java_lang_Object.cc +++ b/runtime/native/java_lang_Object.cc @@ -54,7 +54,7 @@ static jint Object_identityHashCodeNative(JNIEnv* env, jclass, jobject javaObjec return static_cast(o->IdentityHashCode()); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Object, internalClone, "()Ljava/lang/Object;"), FAST_NATIVE_METHOD(Object, notify, "()V"), FAST_NATIVE_METHOD(Object, notifyAll, "()V"), diff --git a/runtime/native/java_lang_StackStreamFactory.cc b/runtime/native/java_lang_StackStreamFactory.cc index 78e38a09146c..6a90fc514f9a 100644 --- a/runtime/native/java_lang_StackStreamFactory.cc +++ b/runtime/native/java_lang_StackStreamFactory.cc @@ -41,7 +41,7 @@ static jint StackStreamFactory_nativeFetchStackFrameInfo(JNIEnv* env, jclass, startLevel, batchSize, startBufferIndex, frameBuffer); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(StackStreamFactory, nativeGetStackAnchor, "()Ljava/lang/Object;"), FAST_NATIVE_METHOD(StackStreamFactory, nativeFetchStackFrameInfo, "(JLjava/lang/Object;III[Ljava/lang/Object;)I"), }; diff --git a/runtime/native/java_lang_String.cc b/runtime/native/java_lang_String.cc index 1ba0028fd3fd..d7bf0013abb2 100644 --- a/runtime/native/java_lang_String.cc +++ b/runtime/native/java_lang_String.cc @@ -133,7 +133,7 @@ static jstring String_doRepeat(JNIEnv* env, jobject java_this, jint count) { return soa.AddLocalReference(result); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(String, charAt, "(I)C"), FAST_NATIVE_METHOD(String, compareTo, "(Ljava/lang/String;)I"), FAST_NATIVE_METHOD(String, concat, "(Ljava/lang/String;)Ljava/lang/String;"), diff --git a/runtime/native/java_lang_StringFactory.cc b/runtime/native/java_lang_StringFactory.cc index e6c03dbcf209..efd1b0cc87eb 100644 --- a/runtime/native/java_lang_StringFactory.cc +++ b/runtime/native/java_lang_StringFactory.cc @@ -294,7 +294,7 @@ static jstring StringFactory_newStringFromUtf8Bytes(JNIEnv* env, jclass, jbyteAr return soa.AddLocalReference(result); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(StringFactory, newStringFromBytes, "([BIII)Ljava/lang/String;"), FAST_NATIVE_METHOD(StringFactory, newStringFromChars, "(II[C)Ljava/lang/String;"), FAST_NATIVE_METHOD(StringFactory, newStringFromString, "(Ljava/lang/String;)Ljava/lang/String;"), diff --git a/runtime/native/java_lang_System.cc b/runtime/native/java_lang_System.cc index 203d98dc4c65..4d50b194cbd3 100644 --- a/runtime/native/java_lang_System.cc +++ b/runtime/native/java_lang_System.cc @@ -239,7 +239,7 @@ static void System_arraycopyBooleanUnchecked(JNIEnv* env, javaDst, dstPos, count); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(System, arraycopy, "(Ljava/lang/Object;ILjava/lang/Object;II)V"), FAST_NATIVE_METHOD(System, arraycopyCharUnchecked, "([CI[CII)V"), FAST_NATIVE_METHOD(System, arraycopyByteUnchecked, "([BI[BII)V"), diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc index e215117df15a..ef06112f5d4c 100644 --- a/runtime/native/java_lang_Thread.cc +++ b/runtime/native/java_lang_Thread.cc @@ -390,7 +390,7 @@ static void Thread_parkVirtualInternal( env->Throw(reinterpret_cast(vm_error)); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Thread, currentThread, "()Ljava/lang/Thread;"), FAST_NATIVE_METHOD(Thread, interrupted, "()Z"), FAST_NATIVE_METHOD(Thread, isInterrupted, "()Z"), diff --git a/runtime/native/java_lang_Throwable.cc b/runtime/native/java_lang_Throwable.cc index 45496b1a3c57..f46b99c2d6e7 100644 --- a/runtime/native/java_lang_Throwable.cc +++ b/runtime/native/java_lang_Throwable.cc @@ -38,7 +38,7 @@ static jobjectArray Throwable_nativeGetStackTrace(JNIEnv* env, jclass, jobject j return Thread::InternalStackTraceToStackTraceElementArray(soa, javaStackState); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Throwable, nativeFillInStackTrace, "()Ljava/lang/Object;"), FAST_NATIVE_METHOD(Throwable, nativeGetStackTrace, "(Ljava/lang/Object;)[Ljava/lang/StackTraceElement;"), }; diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc index c723a1291acc..b2c4d9844c0a 100644 --- a/runtime/native/java_lang_VMClassLoader.cc +++ b/runtime/native/java_lang_VMClassLoader.cc @@ -167,7 +167,7 @@ static jobjectArray VMClassLoader_getBootClassPathEntries(JNIEnv* env, jclass) { MakeTransformRange(Filter(path, dchecked_is_base_dex), get_location))); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(VMClassLoader, findLoadedClass, "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;"), NATIVE_METHOD(VMClassLoader, getBootClassPathEntries, "()[Ljava/lang/String;"), }; diff --git a/runtime/native/java_lang_invoke_MethodHandle.cc b/runtime/native/java_lang_invoke_MethodHandle.cc index 819656fd0572..80f2d04ef0ce 100644 --- a/runtime/native/java_lang_invoke_MethodHandle.cc +++ b/runtime/native/java_lang_invoke_MethodHandle.cc @@ -37,7 +37,7 @@ static void MethodHandle_invokeExactWithFrame(JNIEnv* env, jobject thiz, jobject MethodHandleInvokeExactWithFrame(soa.Self(), handle, frame); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { NATIVE_METHOD(MethodHandle, invokeExactWithFrame, "(Ldalvik/system/EmulatedStackFrame;)V") }; diff --git a/runtime/native/java_lang_invoke_MethodHandleImpl.cc b/runtime/native/java_lang_invoke_MethodHandleImpl.cc index ccd3370ff7dc..87af32488e2e 100644 --- a/runtime/native/java_lang_invoke_MethodHandleImpl.cc +++ b/runtime/native/java_lang_invoke_MethodHandleImpl.cc @@ -63,7 +63,7 @@ static jobject MethodHandleImpl_getMemberInternal(JNIEnv* env, jobject thiz) { return soa.AddLocalReference(h_object.Get()); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { NATIVE_METHOD(MethodHandleImpl, getMemberInternal, "()Ljava/lang/reflect/Member;"), }; diff --git a/runtime/native/java_lang_ref_FinalizerReference.cc b/runtime/native/java_lang_ref_FinalizerReference.cc index 52f6f734d9d3..5dfd542b336b 100644 --- a/runtime/native/java_lang_ref_FinalizerReference.cc +++ b/runtime/native/java_lang_ref_FinalizerReference.cc @@ -42,7 +42,7 @@ static jobject FinalizerReference_getReferent(JNIEnv* env, jobject javaThis) { return soa.AddLocalReference(referent); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(FinalizerReference, makeCircularListIfUnenqueued, "()Z"), FAST_NATIVE_METHOD(FinalizerReference, getReferent, "()Ljava/lang/Object;"), }; diff --git a/runtime/native/java_lang_ref_Reference.cc b/runtime/native/java_lang_ref_Reference.cc index 4c411c8db437..190fe2babe56 100644 --- a/runtime/native/java_lang_ref_Reference.cc +++ b/runtime/native/java_lang_ref_Reference.cc @@ -76,7 +76,7 @@ static void Reference_clearReferent(JNIEnv* env, jobject javaThis) { Runtime::Current()->GetHeap()->GetReferenceProcessor()->ClearReferent(ref); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Reference, getReferent, "()Ljava/lang/Object;"), FAST_NATIVE_METHOD(Reference, clearReferent, "()V"), FAST_NATIVE_METHOD(Reference, refersTo0, "(Ljava/lang/Object;)Z"), diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc index 9ac6e614b67a..f832c134ec1c 100644 --- a/runtime/native/java_lang_reflect_Array.cc +++ b/runtime/native/java_lang_reflect_Array.cc @@ -74,7 +74,7 @@ static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementCl return soa.AddLocalReference(new_array); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Array, createMultiArray, "(Ljava/lang/Class;[I)Ljava/lang/Object;"), FAST_NATIVE_METHOD(Array, createObjectArray, "(Ljava/lang/Class;I)Ljava/lang/Object;"), }; diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc index bff5126b8260..2e1696f999cc 100644 --- a/runtime/native/java_lang_reflect_Constructor.cc +++ b/runtime/native/java_lang_reflect_Constructor.cc @@ -129,7 +129,7 @@ static jobject Constructor_newInstanceFromSerialization(JNIEnv* env, return env->NewObject(allocClass, ctor); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Constructor, getExceptionTypes, "()[Ljava/lang/Class;"), FAST_NATIVE_METHOD(Constructor, newInstance0, "([Ljava/lang/Object;)Ljava/lang/Object;"), FAST_NATIVE_METHOD(Constructor, newInstanceFromSerialization, "(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Object;"), diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc index 1440909032fd..7833c25bc1bc 100644 --- a/runtime/native/java_lang_reflect_Executable.cc +++ b/runtime/native/java_lang_reflect_Executable.cc @@ -359,7 +359,7 @@ static jint Executable_getParameterCountInternal(JNIEnv* env, jobject javaMethod } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Executable, compareMethodParametersInternal, "(Ljava/lang/reflect/Method;)I"), FAST_NATIVE_METHOD(Executable, getAnnotationNative, diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc index 04c1f9da964c..9ffe52ffa394 100644 --- a/runtime/native/java_lang_reflect_Field.cc +++ b/runtime/native/java_lang_reflect_Field.cc @@ -564,7 +564,7 @@ static jboolean Field_isMonotonic0(JNIEnv* env, jobject javaField) { return f->IsMonotonic(); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Field, get, "(Ljava/lang/Object;)Ljava/lang/Object;"), FAST_NATIVE_METHOD(Field, getBoolean, "(Ljava/lang/Object;)Z"), FAST_NATIVE_METHOD(Field, getByte, "(Ljava/lang/Object;)B"), diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc index 92161f8bcd20..cafd63aa3052 100644 --- a/runtime/native/java_lang_reflect_Method.cc +++ b/runtime/native/java_lang_reflect_Method.cc @@ -78,7 +78,7 @@ static jobject Method_invoke(JNIEnv* env, jobject javaMethod, jobject javaReceiv return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Method, getDefaultValue, "()Ljava/lang/Object;"), FAST_NATIVE_METHOD(Method, getExceptionTypes, "()[Ljava/lang/Class;"), FAST_NATIVE_METHOD(Method, invoke, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"), diff --git a/runtime/native/java_lang_reflect_Parameter.cc b/runtime/native/java_lang_reflect_Parameter.cc index fe9e4e3cbf88..716024d93bb4 100644 --- a/runtime/native/java_lang_reflect_Parameter.cc +++ b/runtime/native/java_lang_reflect_Parameter.cc @@ -98,7 +98,7 @@ static jobject Parameter_getAnnotationNative(JNIEnv* env, annotations::GetAnnotationForMethodParameter(method, parameterIndex, klass)); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD( Parameter, getAnnotationNative, diff --git a/runtime/native/java_lang_reflect_Proxy.cc b/runtime/native/java_lang_reflect_Proxy.cc index a89f8274f82e..2ba1d8b6ac4d 100644 --- a/runtime/native/java_lang_reflect_Proxy.cc +++ b/runtime/native/java_lang_reflect_Proxy.cc @@ -37,7 +37,7 @@ static jclass Proxy_generateProxy(JNIEnv* env, jclass, jstring name, jobjectArra soa, name, interfaces, loader, methods, throws)); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Proxy, generateProxy, "(Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/ClassLoader;[Ljava/lang/reflect/Method;[[Ljava/lang/Class;)Ljava/lang/Class;"), }; diff --git a/runtime/native/java_util_concurrent_atomic_AtomicLong.cc b/runtime/native/java_util_concurrent_atomic_AtomicLong.cc index 3f4c6094324a..e9f3a89bb116 100644 --- a/runtime/native/java_util_concurrent_atomic_AtomicLong.cc +++ b/runtime/native/java_util_concurrent_atomic_AtomicLong.cc @@ -30,7 +30,7 @@ static jboolean AtomicLong_VMSupportsCS8(JNIEnv*, jclass) { return QuasiAtomic::LongAtomicsUseMutexes(kRuntimeISA) ? JNI_FALSE : JNI_TRUE; } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { NATIVE_METHOD(AtomicLong, VMSupportsCS8, "()Z"), }; diff --git a/runtime/native/jdk_internal_misc_Unsafe.cc b/runtime/native/jdk_internal_misc_Unsafe.cc index a74dc37ef482..827196a4ce0b 100644 --- a/runtime/native/jdk_internal_misc_Unsafe.cc +++ b/runtime/native/jdk_internal_misc_Unsafe.cc @@ -612,7 +612,7 @@ static jobject Unsafe_allocateInstance(JNIEnv* env, jobject, jclass cls) { return env->AllocObject(cls); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"), FAST_NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"), FAST_NATIVE_METHOD( diff --git a/runtime/native/libcore_io_Memory.cc b/runtime/native/libcore_io_Memory.cc index 66a16ed0ad16..697c0500dfca 100644 --- a/runtime/native/libcore_io_Memory.cc +++ b/runtime/native/libcore_io_Memory.cc @@ -181,7 +181,7 @@ static void Memory_peekShortArray(JNIEnv* env, } // The remaining Memory methods are contained in libcore/luni/src/main/native/libcore_io_Memory.cpp -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Memory, peekByteArray, "(J[BII)V"), FAST_NATIVE_METHOD(Memory, peekCharArray, "(J[CIIZ)V"), FAST_NATIVE_METHOD(Memory, peekDoubleArray, "(J[DIIZ)V"), diff --git a/runtime/native/libcore_util_CharsetUtils.cc b/runtime/native/libcore_util_CharsetUtils.cc index b497f1092d86..d70e55760ec7 100644 --- a/runtime/native/libcore_util_CharsetUtils.cc +++ b/runtime/native/libcore_util_CharsetUtils.cc @@ -137,7 +137,7 @@ static jbyteArray CharsetUtils_toUtf8Bytes(JNIEnv* env, jclass, jstring java_str return soa.AddLocalReference(result); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(CharsetUtils, asciiBytesToChars, "([BII[C)V"), FAST_NATIVE_METHOD(CharsetUtils, toAsciiBytes, "(Ljava/lang/String;II)[B"), FAST_NATIVE_METHOD(CharsetUtils, toIsoLatin1Bytes, "(Ljava/lang/String;II)[B"), diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc index b2e94f90cc32..bfa2c394a684 100644 --- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc +++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc @@ -38,7 +38,7 @@ static void DdmServer_nativeSendChunk(JNIEnv* env, jclass, jint type, Runtime::Current()->GetRuntimeCallbacks()->DdmPublishChunk(static_cast(type), chunk); } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(DdmServer, nativeSendChunk, "(I[BII)V"), }; diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc index e26d804daaac..b5df4559048e 100644 --- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc +++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc @@ -205,7 +205,7 @@ static jbyteArray DdmVmInternal_getThreadStats(JNIEnv* env, jclass) { return result; } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { NATIVE_METHOD(DdmVmInternal, setRecentAllocationsTrackingEnabled, "(Z)V"), NATIVE_METHOD(DdmVmInternal, setThreadNotifyEnabled, "(Z)V"), NATIVE_METHOD(DdmVmInternal, getStackTraceById, "(I)[Ljava/lang/StackTraceElement;"), diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc index b4de838a9eb1..4ee0c741dcc3 100644 --- a/runtime/native/sun_misc_Unsafe.cc +++ b/runtime/native/sun_misc_Unsafe.cc @@ -551,7 +551,7 @@ static void Unsafe_unpark(JNIEnv* env, jobject, jobject jthread) { } } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { FAST_NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"), FAST_NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"), FAST_NATIVE_METHOD(Unsafe, compareAndSwapObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"), diff --git a/runtime/oat/oat_file_manager.cc b/runtime/oat/oat_file_manager.cc index cf54837d4403..cc4bf2eb6076 100644 --- a/runtime/oat/oat_file_manager.cc +++ b/runtime/oat/oat_file_manager.cc @@ -467,11 +467,34 @@ std::vector> OatFileManager::OpenDexFilesFromOat( if (dex_files.empty()) { std::string error_msg; static constexpr bool kVerifyChecksum = true; - ArtDexFileLoader dex_file_loader(dex_location); - if (!dex_file_loader.Open(Runtime::Current()->IsVerificationEnabled(), - kVerifyChecksum, - /*out*/ &error_msg, - &dex_files)) { + + bool res = false; + int fd; + if (!strncmp("/gmscompat_fd_", dex_location, strlen("/gmscompat_fd_")) && + sscanf(dex_location, "/gmscompat_fd_%d", &fd) == 1) { + fd = dup(fd); + struct stat fd_stat; + if (fstat(fd, &fd_stat) != 0) { + LOG(FATAL) << "fstat of " << dex_location << " failed: " << strerror(errno); + _exit(1); // a precaution in case LOG(FATAL) is accidentally or intentionally broken + } + // Don't allow using /gmscompat_fd to load code from an arbitrary file descriptor, e.g. a + // shared memory file descriptor + if (!S_ISREG(fd_stat.st_mode)) { + LOG(FATAL) << dex_location << " has failed the S_ISREG check, st_mode: 0" << std::oct << fd_stat.st_mode; + _exit(1); // a precaution in case LOG(FATAL) is accidentally or intentionally broken + } + unix_file::FdFile fdFile(fd, false); + ArtDexFileLoader dex_file_loader(&fdFile, dex_location); + res = dex_file_loader.Open(Runtime::Current()->IsVerificationEnabled(), kVerifyChecksum, + /*out*/ &error_msg, &dex_files); + } else { + ArtDexFileLoader dex_file_loader(dex_location); + res = dex_file_loader.Open(Runtime::Current()->IsVerificationEnabled(), kVerifyChecksum, + /*out*/ &error_msg, &dex_files); + } + + if (!res) { ScopedTrace fail_to_open_dex_from_apk("FailedToOpenDexFilesFromApk"); LOG(WARNING) << error_msg; error_msgs->push_back("Failed to open dex files from " + std::string(dex_location) diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc index aaaa49f36976..2c6cb8dd0fc0 100644 --- a/sigchainlib/sigchain.cc +++ b/sigchainlib/sigchain.cc @@ -297,6 +297,7 @@ class SignalChain { #if defined(__BIONIC__) linked_sigaction64(signo, &handler_action, &action_); + orig_action_ = action_; linked_sigaction64(signo, nullptr, &handler_action); #else linked_sigaction(signo, &handler_action, &action_); @@ -409,6 +410,7 @@ class SignalChain { int kernel_supported_flags_; #if defined(__BIONIC__) struct sigaction64 action_; + struct sigaction64 orig_action_; #else struct sigaction action_; #endif @@ -490,15 +492,30 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { return; } +#if defined(__BIONIC__) + struct sigaction64 *action = &chains[signo].action_; +#else + struct sigaction *action = &chains[signo].action_; +#endif + +#if defined(__BIONIC__) + if (signo == SIGSEGV && (siginfo->si_code == SEGV_MTEAERR || siginfo->si_code == SEGV_MTESERR) + && mallopt(M_BIONIC_SIGCHAINLIB_SHOULD_INTERCEPT_MTE_SIGSEGV, 0) == 1) + { + LogError("reverting to orig_action_ for MTE SEGV, si_code %d", siginfo->si_code); + action = &chains[SIGSEGV].orig_action_; + } +#endif + // Forward to the user's signal handler. - int handler_flags = chains[signo].action_.sa_flags; + int handler_flags = action->sa_flags; ucontext_t* ucontext = static_cast(ucontext_raw); #if defined(__BIONIC__) sigset64_t mask; - sigorset(&mask, &ucontext->uc_sigmask64, &chains[signo].action_.sa_mask); + sigorset(&mask, &ucontext->uc_sigmask64, &action->sa_mask); #else sigset_t mask; - sigorset(&mask, &ucontext->uc_sigmask, &chains[signo].action_.sa_mask); + sigorset(&mask, &ucontext->uc_sigmask, &action->sa_mask); #endif if (!(handler_flags & SA_NODEFER)) { sigaddset(&mask, signo); @@ -522,9 +539,9 @@ void SignalChain::Handler(int signo, siginfo_t* siginfo, void* ucontext_raw) { siginfo->si_addr = untag_address(siginfo->si_addr); } #endif - chains[signo].action_.sa_sigaction(signo, siginfo, ucontext_raw); + action->sa_sigaction(signo, siginfo, ucontext_raw); } else { - auto handler = chains[signo].action_.sa_handler; + auto handler = action->sa_handler; if (handler == SIG_DFL || (handler == SIG_IGN && signo == SIGSYS && siginfo->si_code == SYS_SECCOMP)) { // We'll only get here if debuggerd is disabled. In that case, whatever next tries to handle diff --git a/test/004-JniTest/jni_test.cc b/test/004-JniTest/jni_test.cc index 429bd94fe045..1518f931ab40 100644 --- a/test/004-JniTest/jni_test.cc +++ b/test/004-JniTest/jni_test.cc @@ -33,7 +33,7 @@ static JavaVM* jvm = nullptr; static jint Java_Main_intFastNativeMethod(JNIEnv*, jclass, jint a, jint b, jint c); static jint Java_Main_intCriticalNativeMethod(jint a, jint b, jint c); -static JNINativeMethod sMainMethods[] = { +static const JNINativeMethod sMainMethods[] = { {"intFastNativeMethod", "(III)I", reinterpret_cast(Java_Main_intFastNativeMethod) }, {"intCriticalNativeMethod", "(III)I", reinterpret_cast(Java_Main_intCriticalNativeMethod) }, }; diff --git a/test/139-register-natives/regnative.cc b/test/139-register-natives/regnative.cc index d9c8b31ac727..083c14c1ecdb 100644 --- a/test/139-register-natives/regnative.cc +++ b/test/139-register-natives/regnative.cc @@ -22,7 +22,7 @@ namespace art { static void foo(JNIEnv*, jclass) { } -static JNINativeMethod gMethods[] = { +static const JNINativeMethod gMethods[] = { { "foo", "()V", reinterpret_cast(foo) } };