如何在Android应用中使用Class.forName()加载系统分区的Java类?
Android运行时加载外部类及AOSP系统集成方案
一、Android应用运行时动态加载外部Jar(非系统分区场景)
Android不支持传统Java的-cp参数指定类路径,需通过DexClassLoader实现动态加载,步骤如下:
- 准备Jar文件:确保
ThatClass.jar包含com.example.ThatClass类,无需提前转dex(DexClassLoader会自动优化生成dex文件)。 - 放置Jar到可访问路径:将Jar放到应用私有目录(如内部存储的
files文件夹),避免权限问题:// 示例:从assets复制Jar到内部存储 InputStream is = getAssets().open("ThatClass.jar"); File jarFile = new File(getFilesDir(), "ThatClass.jar"); FileOutputStream fos = new FileOutputStream(jarFile); byte[] buffer = new byte[1024]; int len; while ((len = is.read(buffer)) != -1) { fos.write(buffer, 0, len); } is.close(); fos.close(); - 使用DexClassLoader加载类:
// 初始化类加载器:参数分别为Jar路径、优化dex输出目录、依赖库路径、父类加载器 DexClassLoader classLoader = new DexClassLoader( jarFile.getAbsolutePath(), getCacheDir().getAbsolutePath(), null, getClassLoader() ); try { // 加载目标类 Class<?> thatClass = classLoader.loadClass("com.example.ThatClass"); // 反射创建实例并调用方法 Object instance = thatClass.getDeclaredConstructor().newInstance(); Method targetMethod = thatClass.getMethod("yourMethodName"); targetMethod.invoke(instance); } catch (Exception e) { e.printStackTrace(); }
注意:若将Jar放在外部存储,需申请对应读写权限(Android 10+建议使用应用专属外部目录)。
二、AOSP构建时将Jar纳入系统分区的方案
若要把ThatClass.jar作为系统库放入系统分区,有以下3种可行方案:
方案1:整合到Framework层
将Jar作为Framework的静态库,所有应用可直接访问:
- 将
ThatClass.jar复制到AOSP源码的frameworks/base/libs/目录。 - 修改
frameworks/base/Android.mk,添加Jar模块定义:include $(CLEAR_VARS) LOCAL_MODULE := ThatClassLib LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := libs/ThatClass.jar LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_MODULE_SUFFIX := $(COMMON_JAVA_PACKAGE_SUFFIX) include $(BUILD_PREBUILT) - 在Framework主模块中引用该库:
# 在frameworks/base/Android.mk的LOCAL_STATIC_JAVA_LIBRARIES中添加 LOCAL_STATIC_JAVA_LIBRARIES += ThatClassLib - 重新编译Framework并刷入系统,应用可直接通过
Class.forName("com.example.ThatClass")加载类。
方案2:独立系统库模块
将Jar打包为独立的系统库,可灵活控制是否预装:
- 在AOSP源码中创建独立模块目录(如
packages/services/ThatClassLib/),放入ThatClass.jar和Android.mk:include $(CLEAR_VARS) LOCAL_MODULE := ThatClassLib LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := ThatClass.jar LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_MODULE_SUFFIX := $(COMMON_JAVA_PACKAGE_SUFFIX) LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES) # 指定输出到system/framework include $(BUILD_PREBUILT) - 在设备配置文件(如
device/<厂商>/<设备>/device.mk)中添加预装配置:PRODUCT_PACKAGES += ThatClassLib - 编译系统后,Jar会被放到
/system/framework/目录。普通应用可通过系统类加载器加载:
若需让应用直接访问,可给应用添加系统签名并设置ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); Class<?> thatClass = systemClassLoader.loadClass("com.example.ThatClass");android:sharedUserId="android.uid.system"。
方案3:加入BootClasspath
将Jar纳入系统核心类路径,让所有应用默认可访问:
- 修改AOSP源码的
build/core/config.mk,在BOOTCLASSPATH中添加Jar路径:BOOTCLASSPATH += $(TARGET_OUT_JAVA_LIBRARIES)/ThatClassLib.jar - 重新编译整个系统,此时
com.example.ThatClass会像系统核心类一样,被所有应用的类加载器自动识别,无需额外代码即可通过Class.forName加载。
内容的提问来源于stack exchange,提问作者DarkSoda
相关产品推荐
相关产品推荐

