You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin编写JNI应用:如何通过Gradle生成Native头文件?

解决Kotlin JNI项目中无法生成.h头文件的问题

问题根源

你当前的Gradle配置只给compileJava任务设置了头文件输出,但Kotlin代码的编译是由compileKotlin任务负责的。javac的头文件生成逻辑只会处理Java编译的字节码,不会自动处理Kotlin编译后的字节码,所以才会出现无法生成.h文件的情况。

解决方案

修改Gradle配置,让Kotlin编译任务完成后,自动调用javac处理生成的字节码来生成JNI头文件,具体步骤如下:

1. 替换原有编译配置

删掉原来的compileJava代码块,添加针对Kotlin编译任务的配置:

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
    kotlinOptions.jvmTarget = "1.8" // 匹配你的项目JVM版本,可根据实际调整
    doLast {
        // 定义头文件输出目录,确保和你原配置路径一致
        def headerOutputDir = file('src/main/java/idk/bluecross/JMM/natives')
        headerOutputDir.mkdirs() // 自动创建目录,避免不存在导致报错

        // 调用javac处理Kotlin生成的字节码,生成JNI头文件
        exec {
            commandLine = [
                "${System.getProperty('java.home')}/bin/javac",
                "-h", headerOutputDir.absolutePath,
                "-cp", sourceSets.main.runtimeClasspath.asPath,
                "${destinationDir}/idk/bluecross/**/*.class" // 替换为你的Kotlin类所在包路径
            ]
        }
    }
}

2. 验证配置效果

执行gradle compileKotlin任务,之后去src/main/java/idk/bluecross/JMM/natives目录下查看,应该能看到对应external fun hi()的.h头文件了。如果没生成,检查一下包路径是否和你的Kotlin类实际路径匹配。

3. 完整修改后的build.gradle

把原来的compileJava块替换成上面的代码后,完整配置如下:

plugins {
    id 'java'
    id 'org.jetbrains.kotlin.jvm' version '1.8.0-RC2'
    id 'application'
    id 'cpp'
}

group 'idk.bluecross'
version '1.0-SNAPSHOT'
application.mainClass = 'idk.bluecross.example.Main'

application {
    applicationDefaultJvmArgs +=
            ["-Djava.library.path=" + file("${buildDir}/libs/jMM/shared").absolutePath]
}

// 替换原来的compileJava配置,新增Kotlin编译后的头文件生成逻辑
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
    kotlinOptions.jvmTarget = "1.8"
    doLast {
        def headerOutputDir = file('src/main/java/idk/bluecross/JMM/natives')
        headerOutputDir.mkdirs()

        exec {
            commandLine = [
                "${System.getProperty('java.home')}/bin/javac",
                "-h", headerOutputDir.absolutePath,
                "-cp", sourceSets.main.runtimeClasspath.asPath,
                "${destinationDir}/idk/bluecross/**/*.class"
            ]
        }
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}

model {
    platforms {
        x64 {
            architecture "x86_64"
        }
    }

    components {
        JMM(NativeLibrarySpec) {
            sources {
                cpp {
                    source {
                        srcDir "src/main/java/idk/bluecross/JMM/natives"
                    }
                }
            }
            targetPlatform "x64"
            binaries.all {
                def jvmHome = System.properties['java.home']
                if (targetPlatform.operatingSystem.macOsX) {
                    cppCompiler.args '-I', "${jvmHome}/include"
                    cppCompiler.args '-I', "${jvmHome}/include/darwin"
                    cppCompiler.args '-mmacosx-version-min=10.4'
                    linker.args '-mmacosx-version-min=10.4'
                } else if (targetPlatform.operatingSystem.linux) {
                    cppCompiler.args '-I', "${jvmHome}/include"
                    cppCompiler.args '-I', "${jvmHome}/include/linux"
                    cppCompiler.args '-D_FILE_OFFSET_BITS=64'
                } else if (targetPlatform.operatingSystem.windows) {
                    cppCompiler.args "-I${jvmHome}/include"
                    cppCompiler.args "-I${jvmHome}/include/win32"
                } else if (targetPlatform.operatingSystem.freeBSD) {
                    cppCompiler.args '-I', "${jvmHome}/include"
                    cppCompiler.args '-I', "${jvmHome}/include/freebsd"
                }
            }
        }
    }
}

classes.dependsOn 'JMMSharedLibrary'

额外提示

  • Kotlin的external fun编译后生成的字节码和Java的native方法结构完全一致,所以用javac处理完全可行
  • 如果你调整了Kotlin类的包路径,记得同步修改${destinationDir}/idk/bluecross/**/*.class中的路径
  • 确保你的JDK环境变量正常,${System.getProperty('java.home')}能正确指向JDK目录

内容的提问来源于stack exchange,提问作者Bluecross

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 20:15:41