2011-11-10 9 views
1

私は非常に単純なエージェントを持っています。基本的には、必要なAgent_OnLoadメソッドのシグネチャのみです。g ++でjvmtiエージェントをコンパイルしても動作しませんが、ccは正常に動作します

g ++でコンパイルした場合。

g++ -g -fno-strict-aliasing -fPIC -fno-omit-frame-pointer -W -Wall -Wno-unused -Wno-parentheses -I. -I../agent_util -I/home/user/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013//include -I/home/user/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013//include/linux -c -o ../src/testagent.o -DMAX_THREADS=1000 -DJVMTI_TYPE=1 ../src/testagent.c 

と共有ライブラリを作成し、エージェント

LD_LIBRARY_PATH=`pwd` /home/mnc/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013//bin/java -agentlib:testagent -version 

上でテストを実行する私は、次のコマンドを使用してコンパイルした場合、すなわちCとしてコンパイルエラーに

Error occurred during initialization of VM 
Could not find agent library on the library path or in the local directory: testagent 
make: *** [test] Error 1 

を取得し、それは大丈夫です。

gcc -Wl,-soname=calltracer.so -g -fno-strict-aliasing -fPIC -fno-omit-frame-pointer -W -Wall -Wno-unused -Wno-parentheses -I. -I../agent_util -I/home/user/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013//include -I/home/user/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013//include/linux -c -o ../src/testagent.o -DMAX_THREADS=1000 -DJVMTI_TYPE=1 ../src/testagent.c 

、その後シュレッドlibにを作成し、それが

LD_LIBRARY_PATH=`pwd` /home/user/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013//bin/java -agentlib:testagent -version 
java version "1.6.0_13" 
Java(TM) SE Runtime Environment (build 1.6.0_13-b03) 
Java HotSpot(TM) Server VM (build 11.3-b02, mixed mode) 

それがうまく動作テストします。

問題は、私が持っているコードです、実際の方法ではなくcであるcです。 C++コードを使用してエージェントを作成することはできますか?私はそれが疑わしいですが、私は何が間違っているのか分かりません。

私のテストエージェントのソースは次のとおりです。カンニングはこれよりはるかに単純です。

/*testagent.c*/ 
#include "jni.h" 
#include "jvmti.h" 


JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) 
{ 
return 0; 
} 

/* Agent_OnUnload() is called last */ 
JNIEXPORT void JNICALL 
Agent_OnUnload(JavaVM *vm) 
{ 
} 

これはここで別のバージョンがあります交流ファイルとして

here's the output from the nm command 
0000046c T Agent_OnLoad 
00000476 T Agent_OnUnload 
00001f18 a _DYNAMIC 
00001ff4 a _GLOBAL_OFFSET_TABLE_ 
     w _Jv_RegisterClasses 
00001f08 d __CTOR_END__ 
00001f04 d __CTOR_LIST__ 
00001f10 d __DTOR_END__ 
00001f0c d __DTOR_LIST__ 
000004d4 r __FRAME_END__ 
00001f14 d __JCR_END__ 
00001f14 d __JCR_LIST__ 
0000200c A __bss_start 
     w [email protected]@GLIBC_2.1.3 
00000480 t __do_global_ctors_aux 
000003b0 t __do_global_dtors_aux 
00002008 d __dso_handle 
     w __gmon_start__ 
00000467 t __i686.get_pc_thunk.bx 
0000200c A _edata 
00002014 A _end 
000004b8 T _fini 
00000348 T _init 
0000200c b completed.7021 
00002010 b dtor_idx.7023 
00000430 t frame_dummy 

をコンパイルしたとき、私はにextern「C」のご提案を追加しましたが、私は以前と同じ結果を持っていた、ライブラリができませんでした[OK]を動作します見つけられた。

/*testagent.c*/ 
#include "jni.h" 
#include "jvmti.h" 

extern "C" { 
    JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) 
    { 
     return 0; 
    } 
} 

/* Agent_OnUnload() is called last */ 
JNIEXPORT void JNICALL 
Agent_OnUnload(JavaVM *vm) 
{ 
} 

はここでnmコマンドnmのコマンドから

000004bc T Agent_OnLoad 
000004c6 T Agent_OnUnload 
0000200c d DW.ref.__gxx_personality_v0 
00001f18 a _DYNAMIC 
00001ff4 a _GLOBAL_OFFSET_TABLE_ 
     w _Jv_RegisterClasses 
00001f08 d __CTOR_END__ 
00001f04 d __CTOR_LIST__ 
00001f10 d __DTOR_END__ 
00001f0c d __DTOR_LIST__ 
00000594 r __FRAME_END__ 
00001f14 d __JCR_END__ 
00001f14 d __JCR_LIST__ 
00002010 A __bss_start 
     w [email protected]@GLIBC_2.1.3 
000004d0 t __do_global_ctors_aux 
00000400 t __do_global_dtors_aux 
00002008 d __dso_handle 
     w __gmon_start__ 
     U __gxx_personality_v0 
000004b7 t __i686.get_pc_thunk.bx 
00002010 A _edata 
00002018 A _end 
00000508 T _fini 
0000039c T _init 
00002010 b completed.7021 
00002014 b dtor_idx.7023 
00000480 t frame_dummy 

トレースからの出力なのは多少異なりますが、どちらもAgent_OnLoadがあります。

これは、どちらの場合でも共有ライブラリを作成するために使用されるコマンドラインです。

ldd libtestagent.so 
linux-gate.so.1 => (0x00544000) 
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00908000) 
/lib/ld-linux.so.2 (0x003a2000) 

は、約15年間、Linuxを使用されてLDDから

アウトケース(G ++)を動作していない、LDDから入れ
cc -g -fno-strict-aliasing -fPIC -fno-omit-frame-pointer -W -Wall -Wno-unused -Wno-parentheses -I. -I../agent_util -I/home/user/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013//include -I/home/user/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013//include/linux -Wl,-soname=libtestagent.so -static-libgcc -mimpure-text -shared -o libtestagent.so ../src/testagent.o -lc 

ldd libtestagent.so 
linux-gate.so.1 => (0x00d96000) 
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x0019a000) 
/lib/ld-linux.so.2 (0x005ee000) 

出力、作業の場合(GCC)は知っていたことはありませんあなたはLD_DEBUG = allをとても役に立ちます。ここで が面白い出力

2689: symbol=__gxx_personality_v0; lookup in file=/home/mnc/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013//bin/java [0] 
     2689: symbol=__gxx_personality_v0; lookup in file=/lib/tls/i686/cmov/libpthread.so.0 [0] 
     2689: symbol=__gxx_personality_v0; lookup in file=/home/mnc/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013/bin/../jre/lib/i386/jli/libjli.so [0] 
     2689: symbol=__gxx_personality_v0; lookup in file=/lib/tls/i686/cmov/libdl.so.2 [0] 
     2689: symbol=__gxx_personality_v0; lookup in file=/lib/tls/i686/cmov/libc.so.6 [0] 
     2689: symbol=__gxx_personality_v0; lookup in file=/lib/ld-linux.so.2 [0] 
     2689: symbol=__gxx_personality_v0; lookup in file=/home/mnc/apps/Genuitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013/jre/lib/i386/server/libjvm.so [0] 
     2689: symbol=__gxx_personality_v0; lookup in file=/lib/tls/i686/cmov/libm.so.6 [0] 
     2689: symbol=__gxx_personality_v0; lookup in file=/home/mnc/apps/javacalltracer/Calltracer/jvmti/libtestagent.so [0] 
     2689: symbol=__gxx_personality_v0; lookup in file=/lib/tls/i686/cmov/libc.so.6 [0] 
     2689: symbol=__gxx_personality_v0; lookup in file=/lib/ld-linux.so.2 [0] 
     2689: /home/mnc/apps/javacalltracer/Calltracer/jvmti/libtestagent.so: error: symbol lookup error: undefined symbol: __gxx_personality_v0 (fatal) 
     2689: 
     2689: file=/home/mnc/apps/javacalltracer/Calltracer/jvmti/libtestagent.so [0]; destroying link map 
Error occurred during initialization of VM 

だ私はポストはので、私は 無効* __ gxx_personality_v0として__gxx_personality_v0追加したこのシンボル のグローバルを追加提案し、これについてはstackoverflowの上で検索を行いました。

g ++でコンパイルすると、JVMはライブラリを検出しました。

のjava、#のGCC

答えて

2

あなたは私たちにtestagent.cの内容を示しませんでした。

私の推測では、あなたがAgent_OnLoad()を定義するときにJNIEXPORTを使用しなかったため、またはJNIEXPORTは、ご使用のプラットフォーム上でextern "C"が含まれていないので、どちらか、C++ name manglingにかまされていることです。

Agent_OnLoad()の定義を囲むことは、extern "C" {}ですべて必要です。

あなたが名前の符号化は、あなたの問題は

nm libtestagent.so | grep Agent_OnLoad 

を実行し、( gcc)作業のために結果を比較すると、壊れた( g++)のバージョンによって実際にあるかどうかを確認することができます。

更新:

Okですので、C++ネームマングリングではありませんでした。次のステップは、動的リンカーがdlopen("libtestagent.so")に失敗した理由を調べることです。コマンドの先頭にLD_DEBUG=allという接頭辞を付けることで、作業出力と非出力出力(出力が大きくなる)を収集し、その違いを探すことができます。

アップデート2:

私がvoid * __ gxx_personality_v0として__gxx_personality_v0追加しました。

これは、問題を解決するための正しい方法ではないため、後でエージェントで実際のC++を使用するときに問題が発生する可能性があります。

問題を解決する正しい方法は、gccではなくg++のライブラリをリンクすることです。これにより、libstdc++.so.6に依存関係が追加されます。これは__gxx_personality_v0と、C++コードに必要なものがたくさんあります。

+0

私のテストエージェントのソースは次のとおりです。カンニングはこれよりはるかに単純です。 – user1040768

+0

ありがとう、私はいくつかの追加情報で更新しました – user1040768

+0

答えの中のupdate2を見てください。 –

関連する問題