我如何知道我的Java应用程序是否使用了“本地代码”?

7
最近的一个问题中,我收到了评论,问我是否在我的应用程序中使用了“本地代码”。现在,我知道有一种方法可以使用称为“JNI”的东西从Java应用程序内部调用传统二进制库(DLL、SO)中的代码。我已经阅读了维基百科的条目,但我从未使用过这个。
我正在使用许多库,其中一些可能使用本地代码,也可能不使用。我没有安装任何SO(在Linux上运行),但我想这并不意味着这些库没有使用任何SO?我必须浏览所有文档(这些文档在库之间的质量差异很大)还是可以对JAR进行一些分析来找出它们是否使用了本地代码?

许多使用操作系统的函数,如IO、线程等都在某个地方使用本地方法。无法编写一个有用的程序而从未使用过本地调用(无论您是否知道)。 - Peter Lawrey
在Linux中,您可以使用类似于以下命令获取已加载库的列表:cat /proc/processId/maps | grep ".so"。在Windows上,Process Explorer可以显示已加载的DLL。最后,您可以安装SecurityManager(在Java中)来跟踪任何被加载的库,该方法称为checkLink,权限名称以“loadLibrary”开头。 - bestsss
4个回答

4
通常使用需要JNI的库需要一些额外的设置(例如将.dll或.so文件放置在正确的位置或设置java.library.path系统属性)。
如果您没有执行任何操作,则很可能没有使用JNI。这也有些可能,因为只有相当专业的库需要JNI。
然而,还有一个名为JNA的包装器,它是JNI的包装器,可以简化其使用,并且有时不需要进行任何显式设置。如果您的库之一使用了它,则更难检测。
如果您获得崩溃转储,则检查其中是否有任何非标准库可以提示用户加载的本地库是否有问题。

我可能会使用“非常专业的库”。例如,有一个库可以在TCP上执行Modbus操作,在我们打补丁之前,它里面有一些串行驱动程序相关的内容... - Hanno Fietz
是的,那肯定可以符合这样的库。感谢修复; -) - Joachim Sauer
哎呀。这是一个对一种明显危险的技术进行包装,但并没有减少其危险性,只是让分析变得更加困难,使用变得更加容易。听起来很可怕。 - Hanno Fietz

1
挑剔一点,每个Java应用程序至少间接地使用JNI。例如,System类包含多个native方法,这些方法映射到本机JRE(可以从其源代码中看到)。
无论您的程序/库是否直接或间接地使用了标准JRE中未包含的其他本机函数,都很难检测。 .dll / .so可能被打包到.jar中,只有在需要时才会提取,因此不需要安装本机库并不能保证它不使用任何本机库。虽然通常应在库文档中说明,因为供应商可能不会为Java运行的每个可想象的系统提供二进制文件。但是要确保,我认为唯一的方法是扫描native方法的源代码。

1
如果一个Java库(jar)使用本地库(Windows上的dll或Linux上的so),那么很有可能它是一个系统范围内和众所周知的库(例如Linux上的glibc)或自定义库。在最后一种情况下,通常将其打包到jar中,因此您可以使用ZIP解压缩器(例如Windows上的7zip)打开它并浏览文件。如果它针对Windows,则应该看到dll文件,如果针对Unix平台,则应该看到so文件,甚至两者都有可能。本地库文件通常留在jar的根级别。
如果jar使用自定义库但与应用程序一起打包,则通常将本地库保留在具有其他应用程序文件的外部文件夹中(在这种情况下没有共识)。在这种情况下,您应该查找应用程序启动器(bat / sh文件)或配置文件(如果lanucher是二进制文件,则为ini / conf文件),并找出JVM配置(其中java.library.path指向)。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接