Android 获取系统内存页大小:sysconf(_SC_PAGESIZE) 与 JNI 实现

最近一个应用准备上架 Google Play,其中某个 SDK 未适配 16KB 内存页大小的设备,因此需要根据设备的内存页大小进行功能屏蔽。具体做法:获取当前设备的内存页大小,若为 16KB,则禁用该 SDK 的相关功能。

先写个工具类,用于获取当前设备的内存页大小。

PageSizeHelper 定义native方法,代码贴出来如下:

java 复制代码
package com.example.nativedemo;

public class PageSizeHelper {
    static {
        System.loadLibrary("page_size_jni");   // should is same with lib name in CMakeLists.txt
    }

    public static native long getPageSize();
}

再这个java文件目录执行 javac -h . PageSizeHelper.java 命令生成头文件:

可以看到生成了头文件和class文件:

其中,com_example_nativedemo_PageSizeHelper.h 文件内容如下:

cpp 复制代码
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_nativedemo_PageSizeHelper */

#ifndef _Included_com_example_nativedemo_PageSizeHelper
#define _Included_com_example_nativedemo_PageSizeHelper
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_nativedemo_PageSizeHelper
 * Method:    getPageSize
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_com_example_nativedemo_PageSizeHelper_getPageSize
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

class文件没用,可以删了。

再右击main目录, 按照下面步骤创建jni目录:

创建好jni目录如下:

再把头文件移动到该jni目录。

再在jni目录里创建c++文件实现其功能, page_size_jni.cpp内容如下:

cpp 复制代码
#include <jni.h>
#include <unistd.h>
#include "com_example_nativedemo_PageSizeHelper.h"

extern "C"
JNIEXPORT jlong JNICALL JNICALL Java_com_example_nativedemo_PageSizeHelper_getPageSize
        (JNIEnv * env, jclass cls) {
    // sysconf(_SC_PAGESIZE) 返回 long,直接转为 jlong
    long pageSize = sysconf(_SC_PAGESIZE);
    return (jlong) pageSize;
}

其中sysconf是一个c语言库函数,获取系统当前的各项配置信息或限制值, 使用它需要包含<unistd.h> 头文件。

Jni目录创建CMakeLists.txt,步骤:

CMakeLists.txt 内容如下:

bash 复制代码
cmake_minimum_required(VERSION 3.4.1)
project("zx_native") # 项目名称 可以随意修改

# 添加一个共享库,名称必须与 System.loadLibrary() 中一致
add_library(
        page_size_jni        # 库名, System.loadLibrary("page_size_jni") 就是加载的这个库
        SHARED               # 动态库
        page_size_jni.cpp    # 源文件
)

# 可选:如果需要查找 log 库等,可以添加
# find_library(log-lib log)
# target_link_libraries(page_size_jni ${log-lib})

修改app/build.gradle.kts :

app/build.gradle.kts完整内容如下:

Groovy 复制代码
plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.compose)
}

android {
    namespace = "com.example.nativedemo"
    compileSdk = 36

    defaultConfig {
        applicationId = "com.example.nativedemo"
        minSdk = 29
        targetSdk = 36
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

        ndk {
            abiFilters.addAll(listOf("arm64-v8a", "armeabi-v7a"))
        }

        externalNativeBuild {
            cmake {
                cppFlags("-std=c++17")
            }
        }

        ndkVersion = "30.0.14904198"
    }

    externalNativeBuild {
        cmake {
            path = file("src/main/jni/CMakeLists.txt")
        }
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
    buildFeatures {
        viewBinding = true
    }
}

dependencies {
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.appcompat)
    implementation(libs.androidx.material)

    // Compose 可以保留
    implementation(libs.androidx.lifecycle.runtime.ktx)
    implementation(libs.androidx.activity.compose)
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.compose.ui)
    implementation(libs.androidx.compose.ui.graphics)
    implementation(libs.androidx.compose.ui.tooling.preview)
    implementation(libs.androidx.compose.material3)

    // MVI核心依赖
    implementation(libs.androidx.lifecycle.viewmodel.ktx)
    implementation(libs.kotlinx.coroutines.android)
    implementation(libs.androidx.recyclerview)
    implementation(libs.androidx.swiperefreshlayout)

    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
}

同步报错:

下载ndk:

下载完再同步就ok了。

在MainActivity测试下:

运行:

ok. 获取到了,看下对不对,用adb命令再看下PAGESIZE值:

ok. 获取到了。

相关推荐
fundroid7 小时前
Google I/O 2026 | Android 全面进化:从操作系统到“智能中枢”
android·jetpack compose·google i/o 2026
zh_xuan8 小时前
Android 复用 .so 库:通过 jniLibs 集成预编译二进制库(获取 Page Size )
android·jni·ndk·内存页大小
匆忙拥挤repeat9 小时前
Android Compose 约束布局
android
好安静9 小时前
Android ShellTransitions 机制完整分析(by DeepSeekV4Pro)
android
事后不诸葛9 小时前
安卓init.rc解析
android·framework
徒手猫9 小时前
myslq 中json 格式的数据如何获取某个属性
android·json
2401_827560209 小时前
【电脑和手机系统】解锁bl后刷LineageOS与Magisk各模块的安装(七)
android·linux·智能手机
超人也会哭️呀10 小时前
ES 混合检索(文本+向量)中的条件处理陷阱——当权限过滤遇到关键词查询
android·大数据·elasticsearch
zuowei288910 小时前
Laravel10.x重磅升级:8大新特性解析
android