5

過去数年間、X25プロトコルを使用するプログラムを作成しました。これはC言語で作成されており、Solaris5.9を搭載したSun-Fireマシンで正常に動作します。最近、同じマシンでjava 6を使用しており、jniを介してjavaを使用できるようにCの古いプログラムを適応させようとしています。だから私は古いCプログラムにいくつかの変更を加え、という名前の共有ライブラリを作成しました x25lib.so

しかし、jniとX25を使用して実行時の問題を発見しました。C関数がJavaからjniを介して呼び出された場合、Cコードは別のCプログラムから呼び出された場合と同じようには機能しません。

具体的には、jniを使用すると、共有ライブラリのCコードは、システムコールが呼び出されるまで正常に機能しconnect()、その後-1を返します。

しかし、別のCプログラムから共有ライブラリの同じCコードを呼び出すと、0(ok)が返されます。

どちらの場合も、共有ライブラリのCコードは外部パラメータを受け取らないため、条件は同じです。Javaから「x25lib.so」共有ライブラリをロードするconnect()際に、Cでの誘導に少し違いがあるかどうかはわかりません。

javaから「truss」コマンドを使用すると、エラーが見つかりました。

/2: connect(5, 0xFD878B75, 112, 1)          Err#22 EINVAL

同じですが、別のCプログラムから共有ライブラリを呼び出します。

connect(4, 0xFFBFE794, 114, 1)          = 0

したがって、純粋なCでのみ問題なく動作します。

solaris 5.9にjniとX25を使用するための別の考慮事項はありますか?

重要:共有ライブラリのCコードは、どちらの場合も同じです。

コンパイル時間:

a。作成x25lib.so

    cc  -w -fd -G -Kpic subs.o -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib -lsockx25
        -lsocket -lnsl -I"/SDK/jdk/include/" -I"/SDK/jdk/include/solaris/"
        -o x25lib.so -h x25lib.so x25jni.c

b。その共有ライブラリを使用してテストCプログラムを作成します。

    cc -w x25lib.so -o x25test x25test.c

where `x25test.c` contains:


    #include <stdio.h>
    main()
    {
        java_x25();
    }

c。Javaの使用:

public class X25 {

        static {
           System.load("/home/x25lib.so");
        }
    public native void ejecutaComando();
}

public class TestX25 {

    public static void main(String ... args) {
    X25 x25 = new X25();

    x25.ejecutaComando();
    }

}

次に、Cコード共有ライブラリで:

/*
 * Class:     X25
 * Method:    ejecutaComando
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_X25_ejecutaComando
  (JNIEnv *env, jobject obj)
{

        java_x25();

}

したがって、最後に、両方のプログラム(java y C)が共有ライブラリ内のまったく同じCコードを呼び出します。

java_x25()
パラメータなしで、同じコードを実行します。

がCから呼び出された場合は正常に機能しますが、Javaから呼び出された場合は失敗するのはなぜですか?

アドバイスありがとうございます。

4

2 に答える 2

1

コメントしてくれてありがとう。別のアプローチを試していたときに解決策を見つけました.jniを使用しないことにしました.代わりに古いCプログラムをJavaからの単純なtcp接続をリッスンするように調整し、x25コードを実行できましたが、驚いたことに、次のような同じランタイムエラーが発生しました. jniを使用:

connect(5, 0xFD8789C5, 112, 1)          Err#22 EINVAL

114 ではなく 112 のサイズを含め、同じ問題でした。

そのため、問題は "-lsockx25" の前に" -lsocket" オプションを使用して新しい C プログラムをコンパイルしたことにあることに気付きました。次に、Googleで検索したところ、同様の問題が見つかりました。

Java X25 Bug ID:4077576 へのリンク

その記事の最後に、sockx25 ライブラリを強制的に最初にロードするオプションLD_PRELOADが記載されています。最後に、解決策は実行時でした:

bash$ export LD_PRELOAD=/opt/SUNWconn/lib/libsockx25.so

bash$ java TestX25

そして、jniを使用してすべてが正常に機能しています。

LD_PRELOAD のリファレンス: Java チューニングへのリンク

于 2012-04-11T21:50:51.340 に答える
0

いくつかの観察結果 (これについてさらに詳しく知りたい場合は、コードを投稿してください。特に、パラメータを に設定する部分connect()):

X.25 over TCP(?) を想定:

  1. マニュアル ページから、 「namelen は、指定されたアドレス ファミリの有効なアドレスのサイズではありません」EINVALが返されます。ここで、は で定義された構造体です。通常は 16 です (2 バイトのアドレス ファミリ (私は予想します) の後に 14 オクテットのアドレス データが続きます)。プログラムは112 または 114 を返します。connect(3socket)namelensockaddr<sys/socket_impl.h>namelenSOCK_STREAMnamelen

  2. name0xFD878B75 を超える失敗した出力のアドレスtruss(1)は奇数です (「偶数ではない」という意味で奇数です)。Solaris の典型的なアラインメント要件を考えると、これは奇妙に思えます。(SPARC か x86 か? コンパイラとフラグは?)。おそらくポインターまたはサイズの問題ですか?

  3. 出力からtruss(1)、Java 呼び出しでスレッドが使用されていることがわかります。ライブラリはスレッドセーフですか?

于 2012-04-10T15:36:27.440 に答える