「java程序dll」JAVA程序的种类有

博主:adminadmin 2023-01-02 02:09:08 700

本篇文章给大家谈谈java程序dll,以及JAVA程序的种类有对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

java 如何调用dll?

JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。

JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。

简单介绍及应用如下:

一、JAVA中所需要做的工作

在JAVA程序中,首先需要在类中声明所调用的库名称,如下:

static {

System.loadLibrary(“goodluck”);

}

在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。

还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具 体实现。如下:

public native static void set(int i);

public native static int get();

然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。

例如程序testdll.java,内容为:

public class testdll

{

static

{

System.loadLibrary("goodluck");

}

public native static int get();

public native static void set(int i);

public static void main(String[] args)

{

testdll test = new testdll();

test.set(10);

System.out.println(test.get());

}

}

用javac testdll.java编译它,会生成testdll.class。

再用javah testdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。

二、C/C++中所需要做的工作

对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。

接上例子。我们先看一下testdll.h文件的内容:

#i nclude jni.h

#ifndef _Included_testdll

#define _Included_testdll

#ifdef __cplusplus

extern "C" {

#endif

JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);

JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);

#ifdef __cplusplus

}

#endif

#endif

在具体实现的时候,我们只关心两个函数原型

JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); 和

JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);

这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVA的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。

好,下面我们用testdll.cpp文件具体实现这两个函数:

#i nclude "testdll.h"

int i = 0;

JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)

{

return i;

}

JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)

{

i = j;

}

编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是goodluck.dll 。把goodluck.dll拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了。

java怎样调用DLL方法

我是通过一个外部的JAR包来间接来获得DLL文件的句柄 的,它就是jacob了,这是java com brige的简写,呵呵, 这个名称起得非常形象吧,我用的版本是jacob 1.9的,你可以到它的官方网站去下载,下载回来的压缩包中会有两个文件我们需要用到的,一个是jacob.dll,一个是jacob.jar,jacob.dll可以将它复制到系统的system32目录下,而jacob.jar文件,直接将它加入到项目的库中就可以了。这两项准备工作完成后,就可以开始尝试调用了。

新建一个类,引入jacob.jar中的两个类,

import com.jacob.activeX.ActiveXComponent;

import com.jacob.com.Dispatch;

然后通过dll的ControllerId来读取DLL文件

public class Print {

private ActiveXComponent printController = null;

private Dispatch printObj = null;/*** 默认controllerId的方法*/public Print(){try{printController = new ActiveXComponent(POSControler.Controler);

printObj = (Dispatch)printController.getObject();

}catch(Exception e){

printObj = new Dispatch();

如果方法dll中的方法是空参数时,直接call一下就可以了,如

Dispatch.call(printObj,setDefaultFont);而调用有参数的方法时,则需要将参数在后面依次传入,注意按顺序噢:

如何解决java调dll报Unable to load library的错误

解决java调dll报Unable to load library的错误可以尝试以下方法:

载入库文件有两个函数,System.load 和 System.loadLibrary。

当使用System.load时,需要输入文件的全路径,例如:System.load(“/tmp/test.so”);

当使用System.loadlibrary时是在系统的library 的目录中需找复合条件的库文件,可以使用-Djava.library.path=[path]参数,来指定Java程序加载库文件的路径,或者将库文件(*.so,*.dll)复制到include的默认路径,Linux一般是/usr/lib目录下,当然你可以编辑/etc/ld.so.conf.d/下的文件,设定自己的库查找路径ldconfig -v|grep xxx看看有没有你的动态库。

Linux还要注意,使用System.loadLibrary(name)方法其中参数内容与Windows有区别,Linux中的的库文件名为libname.so,Windows为name.dll。

在Windows中尽量使用Windows的C/C++编译器生成dll文件,否则会出现问题。

不过具体问题还要具体对待!

java调用dll

调用printf()即可。

第一步是写出对固有方法及它的自变量进行声明的Java代码:

class ShowMsgBox {

public static void main(String [] args) {

ShowMsgBox app = new ShowMsgBox();

app.ShowMessage( "Generated with JNI ");

}

private native void ShowMessage(String msg);

static {

System.loadLibrary( "MsgImpl ");

}

}

在固有方法声明的后面,跟随有一个static代码块,它会调用System.loadLibrary()(可在任何时候调用它,但这样做更恰当)System.loadLibrary()将一个DLL载入内存,并建立同它的链接。DLL必须位于您的系统路径,或者在包含了Java类文件的目录中。根据具体的平台,JVM会自动添加适当的文件扩展名。

1. C头文件生成器:javah

现在编译您的Java源文件,并对编译出来的.class文件运行javah。javah是在1.0版里提供的,但由于我们要使用Java 1.1 JNI,所以必须指定-jni参数:

javah -jni ShowMsgBox

javah会读入类文件,并为每个固有方法声明在C或C++头文件里生成一个函数原型。下面是输出结果——ShowMsgBox.h源文件(为符合本书的要求,稍微进行了一下修改):

/* DO NOT EDIT THIS FILE

- it is machine generated */

#include jni.h

/* Header for class ShowMsgBox */

#ifndef _Included_ShowMsgBox

#define _Included_ShowMsgBox

#ifdef __cplusplus

extern "C " {

#endif

/*

* Class: ShowMsgBox

* Method: ShowMessage

* Signature: (Ljava/lang/String;)V

*/

JNIEXPORT void JNICALL

Java_ShowMsgBox_ShowMessage

(JNIEnv *, jobject, jstring);

#ifdef __cplusplus

}

#endif

#endif

从“#ifdef_cplusplus”这个预处理引导命令可以看出,该文件既可由C编译器编译,亦可由C++编译器编译。第一个#include命令包括jni.h——一个头文件,作用之一是定义在文件其余部分用到的类型;JNIEXPORT和JNICALL是一些宏,它们进行了适当的扩充,以便与那些不同平台专用的引导命令配合;JNIEnv,jobject以及jstring则是JNI数据类型定义。

2. 名称管理和函数签名

JNI统一了固有方法的命名规则;这一点是非常重要的,因为它属于虚拟机将Java调用与固有方法链接起来的机制的一部分。从根本上说,所有固有方法都要以一个“Java”起头,后面跟随Java方法的名字;下划线字符则作为分隔符使用。若Java固有方法“过载”(即命名重复),那么也把函数签名追加到名字后面。在原型前面的注释里,大家可看到固有的签名。欲了解命名规则和固有方法签名更详细的情况,请参考相应的JNI文档。

3. 实现自己的DLL

此时,我们要做的全部事情就是写一个C或C++源文件,在其中包含由javah生成的头文件;并实现固有方法;然后编译它,生成一个动态链接库。这一部分的工作是与平台有关的,所以我假定读者已经知道如何创建一个DLL。通过调用一个Win32 API,下面的代码实现了固有方法。随后,它会编译和链接到一个名为MsgImpl.dll的文件里:

#include windows.h

#include "ShowMsgBox.h "

BOOL APIENTRY DllMain(HANDLE hModule,

DWORD dwReason, void** lpReserved) {

return TRUE;

}

JNIEXPORT void JNICALL

Java_ShowMsgBox_ShowMessage(JNIEnv * jEnv,

jobject this, jstring jMsg) {

const char * msg;

msg = (*jEnv)- GetStringUTFChars(jEnv, jMsg,0);

MessageBox(HWND_DESKTOP, msg,

"Thinking in Java: JNI ",

MB_OK | MB_ICONEXCLAMATION);

(*jEnv)- ReleaseStringUTFChars(jEnv, jMsg,msg);

}

若对Win32没有兴趣,只需跳过MessageBox()调用;最有趣的部分是它周围的代码。传递到固有方法内部的自变量是返回Java的大门。第一个自变量是类型JNIEnv的,其中包含了回调JVM需要的所有挂钩(下一节再详细讲述)。由于方法的类型不同,第二个自变量也有自己不同的含义。对于象上例那样的非static方法(也叫作实例方法),第二个自变量等价于C++的“this”指针,并类似于Java的“this”:都引用了调用固有方法的那个对象。对于static方法,它是对特定Class对象的一个引用,方法就是在那个Class对象里实现的。

剩余的自变量代表传递到固有方法调用里的Java对象。主类型也是以这种形式传递的,但它们进行的“按值”传递

怎样用JAVA调用DLL?

1. 编写范例文档

public class TestNative

{

private native static int Max(int a,int b);

public static void main(String[] args)

{

System.out.println(Max(4,5));

}

static

{

System.loadLibrary("VCdll");

}

}

其中

LoadLibrary中的DLL文件名称可以随便定.只要做好的动态链接库改名成这个字符串就可以了.而native函数的来源就是该动态链接库.

2. 做好该步准备以后,用javac TestNative.java生成TestNative.class. 检验语法.

3. 语法检查通过以后,用javah TestNative生成TestNative.h的C++头文件.

4. 用VC++6.0创建dll文件:

1msdev-new-project-win32 Dynamic-Link Library

2Enter project name (e.g. VCdll)

3choose "An empty DLL project"-finish

4将3生成的TestNative.h和jdk下的jni.h和jni_md.h加入到工程中去

5Create a c++ file, implements the native method. as follows:

//TestNative.cpp

#include "TestNative.h"

JNIEXPORT jint JNICALL Java_TestNative_Max

(JNIEnv * a, jclass b, jint x, jint y)

{

return x y ? x : y;

}

备注:

A 其中的jni.h通常在 jdk\include\ 可以先拷贝到VC安装目录下的include目录下.一劳永逸,以后可以方便使用JNI技术.

B 全部的数据类型需要考虑Java和VC的接口问题.用jint jstring 等.

C 函数名称和自动生成的.h文件中规定的一致.命名规则是: Java_使用类_方法名

6. 全编译一下VC++工程.

如果没有出错,则此时生成动态链接库成功.

把动态链接库VCdll.dll拷贝到TestNative.java所在的目录上.

7.运行java TestNative. OK :-)

java源代码分析----jvm.dll装载过程

简述 众所周知java exe是java class文件的执行程序 但实际上java exe程序只是一个执行的外壳 它会装载jvm dll(windows下 以下皆以windows平台为例 linux下和solaris下其实类似 为 libjvm so) 这个动态连接库才是java虚拟机的实际操作处理所在 本文探究java exe程序是如何查找和装载jvm dll动态库 并调用它进行class文件执行处理的 源代码 本文分析之代码 《JavaTM SDK Standard Edition v fcsCommunity Source Release》 可从sun官方网站下载 主要分析的源代码为 j se\src\share\bin\java cj se\src\windows\bin\java_md c java c是什么东西 java程序 源代码所谓 java程序 包括jdk中的java exe\javac exe\javadoc exe java c源代码中通过JAVA_ARGS宏来控制生成的代码 如果该宏没定义则编译文件控制生成java exe否则编译文件控制生成其他的 java程序 比如 j se\make\java\javac\Makefile(这是javac编译文件)中 $(CD) / /sun/javac ; $(MAKE) $@ RELEASE=$(RELEASE) FULL_VERSION=$(FULL_VERSION)j se\make\sun\javac\javac\Makefile(由上面Makefile文件调用)中 JAVA_ARGS = { \ J ms m\ \ sun tools javac Main\ } 则由同一份java c代码生成的javac exe程序就会直接调用java类方法 sun tools javac Main 这样使其执行起来就像是直接运行的一个exe文件 而未定义JAVA_ARGS的java exe程序则会调用传递过来参数中的类方法 从java c的main入口函数说起 main()函数中前面一段为重新分配参数指针的处理 然后调用函数 CreateExecutionEnvironment 该函数主要查找java运行环境的目录 和jvm dll这个虚拟机核心动态连接库文件路径所在 根据操作系统不同 该函数有不同实现版本 但大体处理逻辑相同 我们看看windows平台该函数的处理(j se\src\windows\bin\java_md c) CreateExecutionEnvironment函数主要分为三步处理 a 查找jre路径 b 装载jvm cfg中指定的虚拟机动态连接库(jvm dll)参数 c 取jvm dll文件路径 实现 a 查找jre路径是通过java_md c中函数 GetJREPath实现的 该函数首先调用GetApplicationHome函数 GetApplicationHome函数调用windowsAPI函数GetModuleFileName取java exe程序的绝对路径 以我的jdk安装路径为例 为 D:\java\j sdk _ \bin\java exe 然后去掉文件名取绝对路径为 D:\java\j sdk _ \bin 之后会在去掉最后一级目录 现在绝对路径为 D:\java\j sdk _ 然后GetJREPath函数继续判断刚刚取的路径+\bin\java dll组合成的这个java dll文件是否存在 如果存在则 D:\java\j sdk _ 为JRE路径 否则判断取得的 D:\java\j sdk _ 路径+\jre\bin\java dll文件是否存在 存在则 D:\java\j sdk _ \jre 为JRE路径 如果上面两种情况都不存在 则从注册表中去查找(参见函数GetPublicJREHome) 函数 GetPublicJREHome先查找 HKEY_LOCAL_MACHINE\Sofare\JavaSoft\Java Runtime Environment\CurrentVersion键值 当前JRE版本号 判断 当前JRE版本号 是否为 做为版本号 如果是则取HKEY_LOCAL_MACHINE\Sofare\JavaSoft\Java Runtime Environment\ 当前JRE版本号 \JavaHome的路径所在为JRE路径 我的JDK返回的JRE路径为 D:\java\j sdk _ \jre b 装载jvm cfg虚拟机动态连接库配置文件是通过java c中函数:ReadKnownVMs实现的 该函数首先组合jvm cfg文件的绝对路径 JRE路径+\lib+\ARCH(CPU构架)+\jvm cfgARCH(CPU构架)的判断是通过java_md c中GetArch函数判断的 该函数中windows平台只有两种情况 WIN 的 ia 其他情况都为 i 我的为i 所以jvm cfg文件绝对路径为 D:\java\j sdk _ \jre\lib\i \jvm cfg 文件内容如下 ## @(#)jvm cfg  / / # # Copyright Sun Microsystems Inc All rights reserved # SUN PROPRIETARY/CONFIDENTIAL Use is subject to license terms # # ### List of JVMs that can be used as an option to java javac etc # Order is important first in this list is the default JVM # NOTE that this both this file and its format are UNSUPPORTED and# WILL GO AWAY in a future release ## You may also select a JVM in an arbitrary location with the# XXaltjvm=jvm_dir option but that too is unsupported# and may not be available in a future release # client KNOWN server KNOWN hotspot ALIASED_TO client classic WARN native ERROR green ERROR(如果细心的话 我们会发现在JDK目录中我的为 D:\java\j sdk _ \jre\bin\client 和 D:\java\j sdk _ \jre\bin\server 两个目录下都存在jvm dll文件 而java正是通过jvm cfg配置文件来管理这些不同版本的jvm dll的 )ReadKnownVMs函数会将该文件中的配置内容读入到一个JVM配置结构的全局变量中 该函数首先跳过注释(以 # 开始的行) 然后读取以 开始的行指定的jvm参数 每一行为一个jvm信息 第一部分为jvm虚拟机名称 第二部分为配置参数 比如行 client KNOWN 则 client 为虚拟机名称 而 KNOWN 为配置类型参数 KNOWN 表示该虚拟机的jvm dll存在 而 ALIASED_TO 表示为另一个jvm dll的别名 WARN 表示该虚拟机的jvm dll不存在但运行时会用其他存在的jvm dll替代执行 而 ERROR 同样表示该类虚拟机的jvm dll不存在且运行时不会找存在的jvm dll替代而直接抛出错误信息 在运行java程序时指定使用那个虚拟机的判断是由java c中函数 CheckJvmType判断 该函数会检查java运行参数中是否有指定jvm的参数 然后从ReadKnownVMs函数读取的jvm cfg数据结构中去查找 从而指定不同的jvm类型(最终导致装载不同jvm dll) 有两种方法可以指定jvm类型 一种按照jvm cfg文件中的jvm名称指定 第二种方法是直接指定 它们执行的方法分别是 java Jjvm cfg中jvm名称 java XXaltjvm=jvm类型名称 或 java J XXaltjvm=jvm类型名称 如果是第一种参数传递方式 CheckJvmType函数会取参数 J 后面的jvm名称 然后从已知的jvm配置参数中查找如果找到同名的则去掉该jvm名称前的 直接返回该值 而第二种方法 会直接返回 XXaltjvm= 或 J XXaltjvm= 后面的jvm类型名称 如果在运行java时未指定上面两种方法中的任一一种参数 CheckJvmType会取配置文件中第一个配置中的jvm名称 去掉名称前面的 返回该值 CheckJvmType函数的这个返回值会在下面的函数中汇同jre路径组合成jvm dll的绝对路径 比如 如果在运行java程序时使用 java J client test 则ReadKnownVMs会读取参数 client 然后查找jvm cfg读入的参数中是否有jvm名称为 client 的 如果有则去掉jvm名称前的 直接返回 client 而如果在运行java程序时使用如下参数 java XXaltjvm=D:\java\j sdk _ \jre\bin\client test 则ReadKnownVMs会直接返回 D:\java\j sdk _ \jre\bin\client 如果不带上面参数执行如 java test 因为在jvm cfg配置文件中第一个存在的jvm为 client 所以函数ReadKnownVMs也会去掉jvm名称前的 返回 client 其实这三中情况都是使用的 D:\java\j sdk _ \jre\bin\client\jvm dll 这个jvm动态连接库处理test这个class的 见下面GetJVMPath函数 c 取jvm dll文件路径是通过java_md c中函数 GetJVMPath实现的 由上面两步我们已经获得了JRE路径和jvm的类型字符串 GetJVMPath函数判断CheckJvmType返回的jvm类型字符串中是否包含了 \ 或 / 如果包含则以该jvm类型字符串+\jvm dll作为JVM的全路径 否则以JRE路径+\bin+\jvm类型字符串+\jvm dll作为JVM的全路径 看看上面的例子 第一种情况 java J client test jvm dll路径为 JRE路径+\bin+\jvm类型字符串+\jvm dll 按照我的JDK路径则为 D:\java\j sdk _ \jre + \bin + \client + \jvm dll 第二种情况 java XXaltjvm=D:\java\j sdk _ \jre\bin\client test 路径为 jvm类型字符串+\jvm dll即为 D:\java\j sdk _ \jre\bin\client + \jvm dll 第三种情况 java test 为 D:\java\j sdk _ \jre + \bin + \client + \jvm dll 与情况一相同 所以这三种情况都是调用的jvm动态连接库 D:\javaj sdk _ \jre\bin\client\jvm dll 处理test类的 我们来进一步验证一下 打开cmd控制台 设置java装载调试E:\work\java_researchset _JAVA_LAUNCHER_DEBUG= 情况一E:\work\java_researchjava J client test ScanDirectory _JAVA_LAUNCHER_DEBUG lishixinzhi/Article/program/Java/hx/201311/26750

java程序dll的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于JAVA程序的种类有、java程序dll的信息别忘了在本站进行查找喔。