2012-04-10 4 views
5

過去にX25プロトコルを使用するプログラムを作成しました。これはC言語で作成され、Solaris 5.9でSun-Fireマシンで正常に動作します。 最近、私たちは同じマシンでjava 6を使って作業しています。私たちはjni経由でjavaを使って作業するために、Cで古いプログラムを適応しようとしています。 だから私は古いCプログラムにいくつかの変更を行い、x25lib.soコードがSolaris 5.9でシステムコール "connect()"を使用するときのjni(java6)およびX25ネイティブコード(C言語)でのエラー

という名前の共有ライブラリを作成した。しかし、私はJNIとX25を使用して実行時の問題を発見したしている:C関数は、JNIを経由して、Javaから呼び出されると、Cのコードがありません別のCプログラムから呼び出されたときと同じように動作しません。その後、システムコールconnect()を呼び出されるまで、JNIを使​​用して、共有ライブラリ内のCコードは正常に動作し

コンクリート、-1を返し、

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

どちらの場合でも、共用ライブラリのCコードは外部パラメータを受け取っていないので条件は同じですが、私の "x25lib.so"共有ライブラリをjavaから少し読み込むと理解できませんCの中でconnect()を誘発する違いは失敗します。 Javaから「トラス」コマンドを使用して

は私がエラーを発見した:

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

同じように、しかし、別のCプログラムから共有ライブラリを呼び出す:

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

ことだからだけでOK動作します純粋な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。 Cコードの共有ライブラリに続いて

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(); 
    } 

} 

:Javaを使用して

/* 
* 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から呼び出されたときに失敗するのはなぜですか?

ありがとうございました。

+0

あなたはあなたのスタンドアロン「C」コードは、あなたのJNIコードと同じですか? – EJP

+0

あなたの答えEJPに感謝します。はい、コードは同じです、それは私の不満です。私は自分の質問を編集し、それがスタンドアロンのCコードと同じコードが呼び出されることがわかるはずのjniコードを追加します。 – aoe

答えて

0

いくつかの観測(あなたは私たちがこれについてより深く行ってみたい場合は、あなたのコードを投稿してください - 特にconnect()にパラメータを設定します一部):

TCP上 X.25と仮定すると(? ):manページEINVALから

  1. connect(3socket)から返されnamelen<sys/socket_impl.h>で定義されたsockaddr構造である「NAMELEN指定されたアドレスファミリのための有効なアドレスのサイズではありません」。 namelenは通常16バイトです(2バイトのアドレスファミリ(私はSOCK_STREAMと予想され、その後に14オクテットのアドレスデータが続きます)。あなたのプログラムは、(「もない」という意味で奇数)namelen 112または114

  2. 0xFD878B75上記のあなたの失敗truss(1)出力のnameのアドレスが奇数を返します。 Solarisの典型的なアライメント要件を考えると、これは奇妙に思えます。 (SPARCまたはx86?どのようなコンパイラとフラグ?)おそらくポインターやsizeofの問題?

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

1

ご意見ありがとうございます。私は別のアプローチを試みている間に解決策を見つけました。私はjniを使用しないことにしました。代わりにJavaからの単純なtcp接続をリスンする古いCプログラムを採用し、x25コードを実行できました。 jniを使用して:

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

114の代わりに114のサイズを使用すると、同じ問題でした。

だから私はこの問題は、それが手掛かりだったので、私は、「-lsockx25」「-lsocket」オプションを使用して新しいCプログラムをコンパイルしていたことだったことに気づきました。その後、私はグーグルで検索し、私は同様の問題が見つかりました:

link to java X25 Bug ID:4077576

をその記事の終わりには、それが最初にロードされsockx25ライブラリを強制するオプションLD_PRELOADを述べています。

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

bash$ java TestX25

し、すべてがJNIを使​​用して正常に動作している:最後に解決策は実行時でした。 LD_PRELOAD用

参考:link to java tuning

関連する問題