java.lang.UnsatisfiedLinkError: C:\Users\Administrator\AppData\Local\Temp\alglib.dll

简介: java.lang.UnsatisfiedLinkError: C:\Users\Administrator\AppData\Local\Temp\alglib.dll

       

文章目录

一、问题

最近在做一个和第三方系统对接的需求。需要对入参进行对称加密。第三方提供了一个jar包,单元测试其中的加密方法时报错:

java.lang.UnsatisfiedLinkError: C:\Users\Administrator\AppData\Local\Temp\alglib7079975575154469256.dll: Can't find dependent libraries
  at java.lang.ClassLoader$NativeLibrary.load(Native Method)
  at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
  at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
  at java.lang.Runtime.load0(Runtime.java:809)
  at java.lang.System.load(System.java:1086)
  at com.ztoon.core.AlgorithmHolder.<clinit>(AlgorithmHolder.java:71)
  at com.ztoon.core.alg.asymmetric.ECC256.privateSign(ECC256.java:29)
  at com.ztoon.core.alg.asymmetric.AsymmetricAlgorithmWrapper.privateSign(AsymmetricAlgorithmWrapper.java:35)
  at cn.gwssi.grant.audit.service.impl.BlockChainServiceImpl.sendHttpRequestByMap(BlockChainServiceImpl.java:547)
  at cn.gwssi.grant.audit.service.impl.BlockChainServiceImpl.getFromHaiDian(BlockChainServiceImpl.java:438)
  at cn.gwssi.grant.audit.service.impl.BlockChainServiceImpl$$FastClassBySpringCGLIB$$f28441a9.invoke(<generated>)
  at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
  at com.alibaba.druid.support.spring.stat.DruidStatInterceptor.invoke(DruidStatInterceptor.java:72)
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
  at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
  at cn.gwssi.grant.audit.service.impl.BlockChainServiceImpl$$EnhancerBySpringCGLIB$$12854599.getFromHaiDian(<generated>)
  at cn.gwssi.grant.audit.service.impl.BlockChainServiceImplTest.testGetFromHaiDian(BlockChainServiceImplTest.java:47)
  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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
  at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
  at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
  at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
  at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
  at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
  at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
  at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
  at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
  at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
  at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
  at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
  at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
  at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
  at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

二、分析

1、源码调试

这个错误是从没见过的,首先调试一下jar包里的源码

image.png

分析一下这个源码的逻辑:

  • 判断操作系统是windows、mac还是Linux,加载不同的动态链接库(DLL)
  • 将jar包里的.dll文件复制到本地
  • System.load(f.toString()):装载dll文件

错误就产生在 System.load(f.toString())

2、.dll文件

2.1、dll是什么

首先看一下.dll文件是什么?

DLL文件即动态链接库文件,是一种可执行文件,它允许程序共享执行特殊任务所必需的代码和其他资源。Windows提供的DLL文件中包含了允许基于Windows的程序在Windows环境下操作许多共享的函数和资源。

DLL文件中存放的是各类程序的函数(子过程)实现过程,当程序需要调用函数时需要先载入DLL,然后取得函数的地址,最后进行调用。使用DLL文件的好处是程序不需要在运行之初加载所有代码,只有在程序需要某个函数的时候才从DLL中取出。另外,使用DLL文件还可以减小程序的体积。

2.2、dll依赖项

当某个程序或 DLL 使用其他 DLL 中的 DLL 函数时,就会创建依赖项。 因此,该程序就不再是独立的,并且如果该依赖项被损坏,该程序就可能遇到问题。 例如,如果发生下列操作之一,则该程序可能无法运行:

  • 依赖 DLL 升级到新版本。
  • 修复了依赖 DLL。
  • 依赖 DLL 被其早期版本覆盖。
  • 从计算机中删除了依赖 DLL。

3、JNI

装载dll文件,这就涉及到另一个知识点:JNI

JNI是Java Native Interface的缩写,指的Java调用本地方法(native method)。本地方法一般是用其它语言(C、C++或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序。

为什么要用本地方法?

因为Java是编译型语言,需要先编译,再运行,虽然有跨平台的好处,但难免效率会低一些。有一些对硬件的操作,Java可能也做不了。所以,这时候就要用Java去调用 C/C++等写的代码。

从结构上来看JNI是一个中间层,具体的调用步骤是这个样子的:java->JNI->C/C++。

image.png

在windows下可以将C/C++程序编译成.dll文件,然后被JNI调用。

可以看一下本地的jdk,里面也有很多动态链接库,Java的很多native方法就是通过这种方式实现的。

image.png

4、dll文件缺少依赖项

经过断点排查分析,

  • jar包中的dll文件复制到了本地
  • 本地的路径和Java加载路径相同

最后觉得:

  • 可能是dll文件缺少依赖项

所以需要查看dll依赖,这里用到了一个工具:Dependency Walker

image.png

用 Dependency Walker 打开 dll文件

image.png

结果发现确实缺少很多依赖项:

image.png

三、解决

1、下载依赖dll

刚开始的解决思路是找到这些缺少的dll,把它们复制到dll相同目录下,找到了一个网站:dll-files.com

image.png

找到了一些缺失的dll,但博主缺失的实在太多了,很多根本找不到。

这是候怀疑是本地windows的环境问题,已经在考虑重装系统了。

2、最终解决

柳暗花明又一村。

最后问题还是解决了——第三方jar包里的dll缺失有一些依赖项,需要手动把这些依赖项拷贝到 文件放入C:\Windows\System32 目录下。

image.png

但是交接人员不太清楚,忘了!

image.png

目录
相关文章
|
1天前
|
Java 开发者
Java中的多线程编程:理解、实现与性能优化
【5月更文挑战第25天】 在Java中,多线程编程是实现并发执行任务的关键手段。本文将深入探讨Java多线程的核心概念,包括线程的创建、生命周期、同步机制以及高级特性。我们将通过实例演示如何有效地创建和管理线程,同时着重分析多线程环境下的性能调优策略和常见问题解决方法。文章旨在为读者提供一个全面的视角,帮助其掌握Java多线程编程的技巧,并在实际开发中避免潜在的并发问题,提升程序的性能和稳定性。
|
1天前
|
安全 Java 测试技术
Java并发编程:理解线程同步和锁
【5月更文挑战第25天】本文深入探讨了Java并发编程的核心概念,即线程同步和锁。通过详细解释这两种机制,我们能够理解它们如何帮助解决多线程环境中的竞态条件问题。此外,文章还提供了一些示例代码,以展示如何在Java中使用这些技术。
|
1天前
|
安全 Java
Java中的多线程编程:从理论到实践
【5月更文挑战第25天】本文将深入探讨Java中的多线程编程,从基础理论到实际应用,为读者提供全面的理解和实践指导。我们将首先介绍多线程的基本概念和重要性,然后详细解析Java中实现多线程的两种主要方式:继承Thread类和实现Runnable接口。接着,我们将探讨如何在多线程环境中处理共享资源,以及如何利用Java的并发工具来管理线程。最后,我们将通过一个实际的例子来演示如何在实际开发中使用多线程。
|
1天前
|
Java 调度
Java并发编程:深入理解线程池
【5月更文挑战第25天】在Java中,线程池是一种管理线程的高效方式,它可以提高系统性能并降低资源消耗。本文将深入探讨Java线程池的原理、使用及优化方法,帮助读者更好地理解和应用线程池技术。
|
1天前
|
Java 调度
Java中线程池的技术
Java中线程池的技术
9 3
|
1天前
|
安全 Java 开发者
Java多线程编程:提升性能的艺术
Java多线程编程:提升性能的艺术
8 2
|
2天前
|
安全 Java 大数据
Java多线程编程:深入理解与应用
Java多线程编程:深入理解与应用
|
2天前
|
安全 Java 数据安全/隐私保护
Java中的多线程编程:基础知识与实践
【5月更文挑战第24天】 在现代软件开发中,多线程编程是提升应用性能和响应速度的关键技术之一。Java 作为一种广泛使用的编程语言,其内置的多线程功能为开发者提供了强大的并发处理能力。本文将深入探讨 Java 多线程的基础概念、实现机制以及在实际开发中的应用。我们将从线程的创建和管理出发,逐步讲解同步机制、死锁问题以及如何利用高级并发工具有效地构建稳定、高效的多线程应用。通过理论结合实例的方式,旨在帮助读者掌握 Java 多线程编程的核心技能,并在实际项目中灵活运用。
|
2天前
|
缓存 安全 Java
JAVA多线程编程与并发控制
```markdown Java多线程编程与并发控制关键点:1) 通过Thread或Runnable创建线程,管理线程状态;2) 使用synchronized关键字和ReentrantLock实现线程同步,防止数据竞争;3) 利用线程池(如Executors)优化资源管理,提高系统效率。并发控制需注意线程安全,避免死锁,确保程序正确稳定。 ```