如何解决在micronaut框架中使用JavaCPP转换为GraalVM原生镜像的Java程序问题
环境:
- 操作系统:Ubuntu 20.04 64 位 LTS。
- JDK:11.0.10
- JavaCPP:1.5.6
- OpenCV:4.5.3
- Micronaut:2.5.9
最近我有一个关于计算机视觉的项目。在这个项目中,它使用 Micronaut 作为主要框架。并且它还使用了用 JavaCPP 构建的 OpenCV。
我自己使用以下命令从 JavaCPP 构建了 OpenCV:
mvn install --projects openblas,opencv -Djavacpp.platform=linux-x86_64
我从 JavaCPP 的 FAQ 中读到它说 JavaCPP 支持 GraalVM NativeImage。
我的代码和build.gradle如下:
build.gradle:
plugins {
id("groovy")
id("com.github.johnrengelman.shadow") version "7.0.0"
id("io.micronaut.application") version "1.5.3"
}
version = "0.1"
group = "com.example"
repositories {
mavenLocal()
mavenCentral()
}
micronaut {
testRuntime("spock2")
processing {
incremental(true)
annotations("com.example.*")
}
}
dependencies {
annotationProcessor("org.projectlombok:lombok")
annotationProcessor("info.picocli:picocli-codegen")
implementation("info.picocli:picocli")
implementation("io.micronaut:micronaut-runtime")
implementation("io.micronaut.picocli:micronaut-picocli")
implementation("javax.annotation:javax.annotation-api")
compileOnly("org.projectlombok:lombok")
runtimeOnly("ch.qos.logback:logback-classic")
compileOnly("org.graalvm.nativeimage:svm")
implementation("io.micronaut:micronaut-validation")
testImplementation("io.micronaut:micronaut-http-client")
implementation('org.bytedeco:opencv:4.5.3-1.5.6-SNAPSHOT')
}
application {
mainClass.set("com.example.NativeJavacppTestCommand")
}
java {
sourceCompatibility = JavaVersion.toVersion("11")
targetCompatibility = JavaVersion.toVersion("11")
}
代码:
package com.example;
import io.micronaut.configuration.picocli.PicocliRunner;
import io.micronaut.context.ApplicationContext;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.opencv.opencv_core.Mat;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
@Command(name = "native-javacpp-test",description = "...",mixinStandardHelpOptions = true)
@Slf4j
public class NativeJavacppTestCommand implements Runnable {
@Option(names = {"-v","--verbose"},description = "...")
boolean verbose;
public static void main(String[] args) throws Exception {
PicocliRunner.run(NativeJavacppTestCommand.class,args);
}
public void run() {
// business logic here
if (verbose) {
System.out.println("Hi!");
}
Mat mat = new Mat();
log.info("Hello,World");
}
}
构建步骤:
sh gradlew shadowJar
sh gradlew nativeImage
当我使用以下命令运行 jar 文件时,它运行良好。
java -Djava.library.path=/opt/javacpp-presets/opencv/target/native/org/bytedeco/opencv/linux-x86_64:/opt/javacpp-presets/openblas/target/native/org/bytedeco/openblas/linux-x86_64 -jar build/libs/native-javacpp-test-0.1-all.jar
当我运行构建的本机映像时。发生以下错误:
./build/native-image/application
10:40:05.322 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [cli]
Warning: Could not create an instance of class org.bytedeco.javacpp.presets.javacpp: java.lang.InstantiationException: Type `org.bytedeco.javacpp.presets.javacpp` can not be instantiated reflectively as it does not have a no-parameter constructor or the no-parameter constructor has not been added explicitly to the native image.
Warning: Could not create an instance of class org.bytedeco.javacpp.presets.javacpp: java.lang.InstantiationException: Type `org.bytedeco.javacpp.presets.javacpp` can not be instantiated reflectively as it does not have a no-parameter constructor or the no-parameter constructor has not been added explicitly to the native image.
Warning: Could not create an instance of class org.bytedeco.javacpp.presets.javacpp: java.lang.InstantiationException: Type `org.bytedeco.javacpp.presets.javacpp` can not be instantiated reflectively as it does not have a no-parameter constructor or the no-parameter constructor has not been added explicitly to the native image.
Warning: Version of org.bytedeco:openblas Could not be found.
Warning: Could not create an instance of class org.bytedeco.openblas.presets.openblas_nolapack: java.lang.InstantiationException: Type `org.bytedeco.openblas.presets.openblas_nolapack` can not be instantiated reflectively as it does not have a no-parameter constructor or the no-parameter constructor has not been added explicitly to the native image.
Warning: Could not create an instance of class org.bytedeco.openblas.presets.openblas: java.lang.InstantiationException: Type `org.bytedeco.openblas.presets.openblas` can not be instantiated reflectively as it does not have a no-parameter constructor or the no-parameter constructor has not been added explicitly to the native image.
Warning: Version of org.bytedeco:opencv Could not be found.
Warning: Could not create an instance of class org.bytedeco.opencv.presets.opencv_core: java.lang.InstantiationException: Type `org.bytedeco.opencv.presets.opencv_core` can not be instantiated reflectively as it does not have a no-parameter constructor or the no-parameter constructor has not been added explicitly to the native image.
Exception in thread "main" java.lang.NoClassDefFoundError: java.lang.classNotFoundException: org.bytedeco.javacpp.presets.javacpp
at org.bytedeco.javacpp.Loader.load(Loader.java:1217)
at org.bytedeco.javacpp.Loader.load(Loader.java:1157)
at org.bytedeco.javacpp.Loader.load(Loader.java:1133)
at org.bytedeco.opencv.opencv_core.AbstractArray.<clinit>(AbstractArray.java:18)
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:375)
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:295)
at java.lang.class.ensureInitialized(DynamicHub.java:553)
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:260)
at java.lang.class.ensureInitialized(DynamicHub.java:553)
at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:260)
at com.example.NativeJavacppTestCommand.run(NativeJavacppTestCommand.java:30)
at picocli.CommandLine.executeUserObject(CommandLine.java:1939)
at picocli.CommandLine.access$1300(CommandLine.java:145)
at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2352)
at picocli.CommandLine$RunLast.handle(CommandLine.java:2346)
at picocli.CommandLine$RunLast.handle(CommandLine.java:2311)
at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2179)
at picocli.CommandLine.execute(CommandLine.java:2078)
at io.micronaut.configuration.picocli.PicocliRunner.run(PicocliRunner.java:137)
at io.micronaut.configuration.picocli.PicocliRunner.run(PicocliRunner.java:114)
at com.example.NativeJavacppTestCommand.main(NativeJavacppTestCommand.java:22)
Caused by: java.lang.classNotFoundException: org.bytedeco.javacpp.presets.javacpp
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:64)
at java.lang.class.forName(DynamicHub.java:1308)
at org.bytedeco.javacpp.Loader.load(Loader.java:1212)
... 20 more
如何让我的代码与原生图像一起运行?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。