这里写自定义目录标题
- 1、出错代码:首先这段代码没有语法或逻辑问题
- 2、奇怪现象及排查过程:
- 2.1、在springboot Junit的单元测试中,DetectServiceImpl加载正常,spring主类启动正常,方法能正常调用。
- 2.2、如果正常启动项目,即执行springboot的主类Application.class的main方法,DetectServiceImpl加载异常,”Mat mat = new Mat(3, 3, CvType.CV_8UC3);“会报错,具体异常如下。
- 2.3、具体查询“java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(III)J”错误,大多是说连接本地opencv库异常,即未加载类似"lib/opencv_java455.dll"的本地动态库文件。大多数情况加下面的语句就可解决
- 2.4、单独开文件测试“Mat mat = new Mat(3, 3, CvType.CV_8UC3);”,代码如下,运行正常
- 3、解决措施
- 4、总结
1、出错代码:首先这段代码没有语法或逻辑问题
@Service
@Slf4j
public class DetectServiceImpl implements IDetectService {
......
static { // 执行顺序1
// 得保证先执行该语句,用于加载库,才能调用其他操作库的语句,
// 设置本地库路径 这句话很重要,如果没有,下面这个函数将报错:Mat img = Imgcodecs.imread(path);
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
System.out.println("DetectServiceImpl Loading Lib: opencv");
}
/**
*
* 类初始化调用顺序: Constructor >> @Autowired >> @PostConstruct
*/
@PostConstruct
public void init() { // 执行顺序3
Mat mat = new Mat(3, 3, CvType.CV_8UC3);// 出错处!!!!!!!!!!
System.out.println("mat113 = " + mat.dump());
}
public DetectServiceImpl() { // 执行顺序2
this.env = OrtEnvironment.getEnvironment();
System.out.println("DetectServiceImpl object ok");
}
.......//执行顺序1-3
}
-
出错语句: Mat mat = new Mat(3, 3, CvType.CV_8UC3);
-
日志报错:Caused by: java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(III)J
-
已加载opencv动态库,但依然报上面的错误
2、奇怪现象及排查过程:
2.1、在springboot Junit的单元测试中,DetectServiceImpl加载正常,spring主类启动正常,方法能正常调用。
“Mat mat = new Mat(3, 3, CvType.CV_8UC3);”不报错
public class DetectServiceTest extends BaseTest {
@Autowired
private IDetectService detectService;
。。。。。。
。。。。。。
}
2.2、如果正常启动项目,即执行springboot的主类Application.class的main方法,DetectServiceImpl加载异常,”Mat mat = new Mat(3, 3, CvType.CV_8UC3);“会报错,具体异常如下。
异常日志:
22:09:50.718 [restartedMain] INFO o.a.s.c.e.EhCacheManager - [getCache,169] - Using existing EHCache named [sys-dict]
DetectServiceImpl Loading Lib: opencv
DetectServiceImpl object ok
22:09:51.006 [restartedMain] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - [refresh,591] - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'yoloDetectController': Unsatisfied dependency expressed through field 'detectService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'detectServiceImpl': Invocation of init method failed; nested exception is java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(III)J
22:09:51.006 [restartedMain] INFO c.a.d.p.DruidDataSource - [close,2174] - {dataSource-1} closing ...
22:09:51.006 [restartedMain] INFO c.a.d.p.DruidDataSource - [close,2247] - {dataSource-1} closed
22:09:51.006 [restartedMain] INFO o.a.c.c.StandardService - [log,173] - Stopping service [Tomcat]
22:09:51.034 [restartedMain] ERROR o.s.b.SpringApplication - [reportFailure,870] - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'yoloDetectController': Unsatisfied dependency expressed through field 'detectService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'detectServiceImpl': Invocation of init method failed; nested exception is java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(III)J
。。。。。。
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'detectServiceImpl': Invocation of init method failed; nested exception is java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(III)J
。。。。。。
Caused by: java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(III)J
at org.opencv.core.Mat.n_Mat(Native Method)
at org.opencv.core.Mat.<init>(Mat.java:32)
at com.ruoyi.ai.service.impl.DetectServiceImpl.init(DetectServiceImpl.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)
... 37 common frames omitted
也就代码相同情况下,都是调用中opencv中的Mat对象的方法,用springboot的主类Application.class的main方法启动就异常,如果用spring test启动就无异常
2.3、具体查询“java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(III)J”错误,大多是说连接本地opencv库异常,即未加载类似"lib/opencv_java455.dll"的本地动态库文件。大多数情况加下面的语句就可解决
static {
// 得保证先执行该语句,用于加载库,才能调用其他操作库的语句,
// 设置本地库路径 这句话很重要,如果没有,下面这个函数将报错:Mat img = Imgcodecs.imread(path);
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
System.out.println("DetectServiceImpl Loading Lib: opencv");
}
其实项目中DetectServiceImpl类原本就有上面这个加载语句。
实施措施:在程序几个必经路口都加上上面的代码,都未报错,重复加载的异常也没有出现
2.4、单独开文件测试“Mat mat = new Mat(3, 3, CvType.CV_8UC3);”,代码如下,运行正常
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
public class Test23 {
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // 得保证先执行该语句,用于加载库,才能调用其他操作库的语句,
System.out.println("Test23 Loading Lib: opencv");
}
public static void main(String[] args) {
//System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat mat = new Mat(3, 3, CvType.CV_8UC3);
System.out.println("mat111 = " + mat.dump());
}
}
经过上面3个步骤的测试,这个出错十分鬼怪,代码一致情况下,执行却不一样。对于”new Mat(3, 3, CvType.CV_8UC3)“语句报“java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(III)J”这个错误,
-
不使用springboot进行单独测试,程序正常
-
使用springboot的主类Application.class启动,程序异常
-
使用spring 单元测试junit启动,程序正常
3、解决措施
在google上搜索这个问题很久(“springboot 运行java.lang.UnsatisfiedLinkError org.opencv.core”),有两三个题主提到
可能是spring-boot-devtools的问题!!!!!!!!
在pom.xml中注释掉spring-boot-devtools就解决了!!!!!!
注释以下内容:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency>
修正后正常时的日志:
22:15:52.947 [main] INFO o.a.s.c.e.EhCacheManager - [getCache,169] - Using existing EHCache named [sys-dict]
22:15:52.947 [main] INFO o.a.s.c.e.EhCacheManager - [getCache,169] - Using existing EHCache named [sys-dict]
DetectServiceImpl Loading Lib: opencv
DetectServiceImpl object ok
mat113 = [ 0, 101, 110, 115, 111, 114, 40, 105, 110;
116, 54, 52, 41, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 15, 0, 0]
DetectUtils Loading Lib: opencv
22:15:54.029 [main] INFO o.q.i.StdSchedulerFactory - [instantiate,1220] - Using default implementation for ThreadExecutor
22:15:54.044 [main] INFO o.q.c.SchedulerSignalerImpl - [<init>,61] - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
22:15:54.044 [main] INFO o.q.c.QuartzScheduler - [<init>,229] - Quartz Scheduler v.2.3.2 created.
22:15:54.044 [main] INFO o.q.s.RAMJobStore - [initialize,155] - RAMJobStore initialized.
4、总结
- spring-boot-devtools可能会使opencv native 动态链接库加载异常,导致调用Mat对象的方法异常,报“java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat(III)J”错误