プログラマメモ2 - programmer no memo2

[java][jni][windows]プロセス同期だミューテックス 2008/10/28

Javaです。Windowsです。ミューテックスです。
相互排他の処理でミューテックスです。


注意点、CloseHandleは重要かも。存在チェックのためにCreateMutex使ってもCloseHandleしたほうがよい!?

Javaから呼び出して、ミューテックスを作ったJavaがexitするとミューテックスをリリースしてくれているようなので、まず存在チェックして、なければCreateMutexする流れでよいと思う。
もちろんアプリケーションの起動シーケンス、環境、がシビアでない場合だけど。。。

JNIで、GetStringUTFCharsしたら、ReleaseStringUTFCharsを忘れないこと、繰り返し実行で、メモリリークよくわかる。Orz....

かっこわるいですがとりあえず、JNIコード(Cベース)

JNIEXPORT jboolean JNICALL Java_WindowsMutex_existMutex
(JNIEnv *env, jobject obj, jstring name)
{

const char *sname = (*env)->GetStringUTFChars(env, name, NULL);

HANDLE hMutex = CreateMutex(NULL, FALSE, sname);

if(hMutex == NULL){
(*env)->ReleaseStringUTFChars(env, name, sname);
return FALSE;
}

//既に存在している。
if(GetLastError() == ERROR_ALREADY_EXISTS){
CloseHandle(hMutex);
(*env)->ReleaseStringUTFChars(env, name, sname);
return TRUE;
}

CloseHandle(hMutex);
(*env)->ReleaseStringUTFChars(env, name, sname);
return FALSE;
}

[java][windows]共有メモリ - ファイルマッピング 2008/10/27

Javaです。windowsです。JNIで共有メモリです。
ファイルマッピングを使ってです。


ソースコード参考(まんまですが....)


動作させていません。(>_<)!
static {
System.loadLibrary("WindowsSharedMemory");
};

public native int CreateFileMapping();

public native int MapViewOfFile(int handle);

public native int ReadMemory(int addr);

public native int WriteMemory(int addr, int data);

public native boolean CloseMemory(int handle, int addr);



JNIのコード
#include <windows.h>
#include "jni.h"

JNIEXPORT jint JNICALL Java_WindowsSharedMemory_CreateFileMapping(JNIEnv *env, jobject obj) {
return((jint)CreateFileMapping((HANDLE)0xFFFFFFFF, NULL,
PAGE_READWRITE, 0, 0x100, "SharedMemory"));
};

JNIEXPORT jint JNICALL Java_WindowsSharedMemory_MapViewOfFile(JNIEnv *env, jobject obj, jint handle) {
return((jint)MapViewOfFile((HANDLE)handle, FILE_MAP_ALL_ACCESS, 0, 0, 0));
};

JNIEXPORT jint JNICALL Java_WindowsSharedMemory_ReadMemory(JNIEnv *env, jobject obj, jint addr) {
return((jint)(*(unsigned char *)addr));
};

JNIEXPORT jint JNICALL Java_WindowsSharedMemory_WriteMemory(JNIEnv *env, jobject obj, jint addr, jbyte data) {
return(*((unsigned char *)addr) = data);
};

JNIEXPORT jboolean JNICALL Java_WindowsSharedMemory_CloseMemory(JNIEnv *env, jobject obj, jint handle, jint addr) {
UnmapViewOfFile((void *)addr);
return((jboolean)CloseHandle((HANDLE)handle));
};

こういうふうにした。java.lang.UnsatisfiedLinkError: xxxl: Can't find dependent libraries 2008/09/21

Windowsです。Javaです。

ネイティブなライブラリを読み込むようにして下記のようなエラーがでた場合。

java.lang.UnsatisfiedLinkError: no xxx in java.library.path

これだとパスに必要なDLLを置くか、DLLのある場所にパスを通せばよいわけです。
Javaコマンドに引数追加。
-Djava.library.path=


次に、パスは設定したが下記のようなエラーがでる場合。
java.lang.UnsatisfiedLinkError: xxxl: Can't find dependent libraries

これは、読み込んだライブラリがさらに他のライブラリに依存しているということになります。

じゃ何が足りないのかを探る方法です。
僕がとったアプローチです。
コードギア(ボーランド)のbcc55についているtdumpというコマンドを使ってDLL他の何に依存しているか調べます。



何やらぞろぞろダンプしてくれます。
それっぽい記述をみつけます。

Imports from XXXX.DLL

って感じで記述されているところがそれっぽいです。

つぎに、そのDLLがあればパスに追加してみます。
そのDLLをもっていなければ、みつけてきます。



こういった手順でとりあえず必要なものがそろうかもしれません。
乱暴なやりかたかも....

javaからMacアドレス ~ Windows編 2008/07/17
2008/07/22

Javaです。
Windowsです。JavaからMACアドレスの取得についてです。

現時点で思いつくであろう方法は3種類です。
(A)OS付属のコマンドをexecして、パスして取得
(B)Java6を使う
(C)JNIを使ってLibから取得

ベストなのは(B)だと思います。


Java6が使えない環境は、残念ながら(A),(C)ですかね。
Javaだといいつつ、Windows専用アプリを開発してたりのですが、どうもWindowsOSのバージョン(XP、VISTA)でipconfigが返してくれる文字列違ったりしたので、深く追求せず、(C)を採用することにしました。

すでに試みている人がいたので
そのまんまコードを参考にしつつ。

もうここ数年C,C++使っていなかったので、思い出しつつ。
コンパイル環境は、WindowsXPで、BorlandのBCC55を使いました。

ボーランドのコンパイラの使い方は、Borland C++ Compiler 5.5日本語版のインストールの方法が参考になりました。

JNIを使っての開発はここがJavaでHello World JNI編いい感じですね。あとここもcivic site : JNIを使ってみる

javahを使ってごにょごにょと。

その他、WindowsでのMacアドレス取得のための参考

で、僕が一番はまったのは、bcc32のリンカの動作というかコンパイルしてオブジェクト作ったあとのための処理でした。

bcc32を使って、下記のようなエラーがでました。
Error: 外部シンボル 'GetIfTable' が未解決


それで、下記のサイトでの説明が、しっくり。
C入門14

bcc32 -I"C:\Program Files\Java\jdk1.6.0\include" -I"C:\Program Files\Java\jdk1.6.0\include\win32" -tWD GetMacAddress.cpp C:\borland\bcc55\Lib\PSDK\iphlpapi.lib


リブを最後に指定してあげて解決。

以下コードです。

気まぐれなる日々さんのそのまんまだったりしかすが....

Java
class GetMacAddress {
static {
System.loadLibrary("GetMacAddress");
}
public native String getMacAddress();
}


ネイティブコード(Win32)
#include <windows.h>
#include <iphlpapi.h>
#include "GetMacAddress.h"

JNIEXPORT jstring JNICALL Java_GetMacAddress_getMacAddress
(JNIEnv *env, jobject obj) {

char buf[1024];
DWORD d=0 ;

GetIfTable( NULL , &d, FALSE );

PMIB_IFTABLE IfTable = (PMIB_IFTABLE)new char[d] ;

if( IfTable ){
if( GetIfTable( (PMIB_IFTABLE)IfTable,&d,FALSE) == NO_ERROR ){
wsprintf(buf,"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x"
,(unsigned char)IfTable->table[0].bPhysAddr[0]
,(unsigned char)IfTable->table[0].bPhysAddr[1]
,(unsigned char)IfTable->table[0].bPhysAddr[2]
,(unsigned char)IfTable->table[0].bPhysAddr[3]
,(unsigned char)IfTable->table[0].bPhysAddr[4]
,(unsigned char)IfTable->table[0].bPhysAddr[5]
);
}
}

return env->NewStringUTF(buf);
}



※Javaを使っているのに、Linux、MacOSで動作させることを頭から放棄するのも気概がないというか、センスがないというか残念な話なのですが。

2008-07-22
ふと検索かけたら、自分のブログが検索にひっかかった。
書いたの2年前なんですよね。その間、お仕事で新しいことしていない....Orz...

あと、どうもXP,Vistaで違いがあるようです。

もしかして、取得した値がイーサネットかどうかという判断をさせる必要があるかもしれませんね。ふぅ。

というわけで上記のOKWaveを参考にして、typeとspeedを使ってイーサネットを判断?させてみました。手元の環境では、XP,vistaでうまくいっているようにみえますが、いろいろな環境でためさないと確信できませんね。

とても参考になったサイトは、ここです。

JNIEXPORT jstring JNICALL Java_GetMacAddress_getMacAddress
(JNIEnv *env, jobject obj) {

char buf[1024];
DWORD d=0 ;

GetIfTable( NULL , &d, FALSE );

PMIB_IFTABLE IfTable = (PMIB_IFTABLE)new char[d];

if( IfTable ){
if( GetIfTable( (PMIB_IFTABLE)IfTable,&d,FALSE) == NO_ERROR ){
for(int i=0;i< (int)IfTable->dwNumEntries;i++ ){
int type = (int)IfTable->table[i].dwType;
int speed = (int)IfTable->table[i].dwSpeed;
if( type == 6
&& (10000000000 == speed
|| 1000000000 == speed
|| 100000000 == speed )){
wsprintf(buf,"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x"
,(unsigned char)IfTable->table[i].bPhysAddr[0]
,(unsigned char)IfTable->table[i].bPhysAddr[1]
,(unsigned char)IfTable->table[i].bPhysAddr[2]
,(unsigned char)IfTable->table[i].bPhysAddr[3]
,(unsigned char)IfTable->table[i].bPhysAddr[4]
,(unsigned char)IfTable->table[i].bPhysAddr[5]
);
break;
}
}
}
delete [] IfTable;
}

return env->NewStringUTF(buf);
}