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. 获取到了。

相关推荐
帅次1 小时前
Android 高级工程师面试:Java 基础知识 近1年高频追问 22 题
android·java·面试
私人珍藏库2 小时前
[Android] zip解压缩管理-全格式压缩包一键解压+打包
android·app·生活·工具·多功能
雨白3 小时前
C语言:动态内存分配
android
Android-Flutter4 小时前
android compose 自定义Painter绘制图形 使用
android·kotlin·compose
我是一颗柠檬4 小时前
【Java项目技术亮点】覆盖索引与索引下推优化
android·java·开发语言
vigor5125 小时前
MySQL通过Mango实现分库分表
android·数据库·mysql
阿pin8 小时前
Android随笔-Zygote中fork究竟是什么?
android·zygote·fork
Go-higher9 小时前
DriverTest 驾考知识卡片学习助手 —— 一款基于 Jetpack Compose 的现代 Android 学习APP
android·学习
安卓修改大师9 小时前
安卓修改大师APK控件修改实战教程
android