2016-08-17 4 views
0

私はASMライブラリを使ってバイトコードを生成し、Unsafe.defineAnonymousをクラスとしてロードします。どちらもほとんどの場合に機能しますが、しばらくしてから失敗します。次に、出力されたバイトコードに何らかのデバッグ命令を追加して何かを出力し、出力が2週間混乱させました。Javaバイトコード変数インデックス0のclassNameが異常です

(GWTはGuardWithTestHandleの略です)

1、DYNGWT70とDYNGWT73の2つのクラスが生成され、両方ともUnsafeを使用してロードされます。各クラスに対して、インスタンスが1つだけ作成されます。

public class java.lang.invoke.DYNGuardWithTestHandle70 extends java.lang.invoke.BaseTemplate{ 
    public org.jruby.runtime.builtin.IRubyObject inlinedMethod(org.jruby.runtime.ThreadContext, org.jruby.runtime.builtin.IRubyObject, org.jruby.runtime.builtin.IRubyObject) throws java.lang.Throwable; 
    flags: ACC_PUBLIC 
    Code: 
     stack=8, locals=22, args_size=4 
     0: aload_0 
     1: aload_0 
     2: ldc   #29     // String This is Guard java/lang/invoke/DYNGuardWithTestHandle70 
     4: invokestatic #32     // Method java/lang/invoke/BaseTemplate.tempDebug:(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;)V 
     7: astore  4 
     9: aload   4 
..... 
} 
} 

protected static void tempDebug(MethodHandle mh, String name){ 
    System.err.println("___________Debug: "+mh.getClass().getName()+", "+mh.toString()+ " message="+name); 
} 

DYNGWT73は同様の構造を有する: は、DYNGWT70のレイアウトのようなものです。

しかし、最初tempDebugための出力です:私はmh.getClass().getName()java.lang.invoke.DYNGuardWithTestHandle73/0000000052DFAE40であることを理解することはできません

___________Debug: java.lang.invoke.DYNGuardWithTestHandle73/0000000052DFAE40, MethodHandle(ThreadContext,IRubyObject,IRubyObject)IRubyObject uid:9a7bf505-8845-4594-9cf8-69f392eef869 message= This is Guard java/lang/invoke/DYNGuardWithTestHandle70 
...... 
16/Aug/2016:22:13:42:834 -0300 [main] DEBUG java.lang.invoke.BaseTemplate - TypeInconsistException [_mh=MethodHandle(ThreadContext,IRubyObject,IRubyObject)IRubyObject uid:e064b157-f615-4f20-b386-947fc20c61ad, _exce=***** false (Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject; (Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/builtin/IRubyObject;J)Lorg/jruby/runtime/builtin/IRubyObject;] 
TypeInconsistException [_mh=MethodHandle(ThreadContext,IRubyObject,IRubyObject)IRubyObject uid:e064b157-f615-4f20-b386-947fc20c61ad, _exce=***** false (Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject; (Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/builtin/IRubyObject;J)Lorg/jruby/runtime/builtin/IRubyObject;] 
    at java.lang.invoke.BaseTemplate.debugCompareReceiverTypeMethodDesc(BaseTemplate.java:59) 
    at java.lang.invoke.DYNGuardWithTestHandle70.0000000052B50680.inlinedMethod(Unknown Source) 
    at java.lang.invoke.DYNGuardWithTestHandle70.0000000052B50680.invokeExact_thunkArchetype_L(Unknown Source) 
    at java.lang.invoke.MutableCallSiteDynamicInvokerHandle.invokeExact_thunkArchetype_X(MutableCallSiteDynamicInvok 

、それが何かDYNGuardWithTestHandle**70**/0000000052DFAExxx である必要があり、ここでスタックを掲示する目的は、それがDYN70のメソッドの実行中であることを示すことです例外は混乱している点に関連しています。

頻度は高いものの、このエラーは必ずしも発生しません。誰もが似たような奇妙なケースを経験しましたか?あなたの提案をありがとう。

+0

エラーですか?あなたの期待と現実との違いは? – EJP

+0

これはデバッグ文だけです。インデックス0の変数は、** DYNGuardWithTestHandle70 **である必要があります。ここでは73なので、DYNGWT70でしか動作しない後のメソッド呼び出し命令にエラーが発生します。 –

+0

私は 'MethodHandle'のカスタムサブクラスを作成することをお勧めします。それはトラブルを求めるようなものです。生成されたコードにダイレクト・ハンドルを使用し、JVMにインライン展開をさせるというクリーンな方法と比べて、意味がありません。そしてそれはあなたがフォーカスを失う原因になります。例外は、1つのシグネチャにのみ存在する 'long'パラメータを示します。これはもちろん矛盾した型です。 – Holger

答えて

0

安全でない非標準APIを使用する場合は、少なくともコメントをお読みください。内部APIにはまったく依存しない方がいいです。 匿名クラスを定義しています - 有効なの名前はとは限りません。 Unsafe.defineAnonymousClass

The commentsは言う:

// When you load an anonymous class U, it works as if you changed its name just before loading, 
// to a name that you will never use again. Since the name is lost, no other class can directly 
// link to any member of U. 

ので、/0000000052DFAE40を意図的にdefineAnonymousClassによって追加されます。たとえば、同じクラスバイトを2回読み込むことができます(通常のClassLoaderではできないもの)。名前の衝突を避けるために、別の接尾辞が生成されます。

+0

あなたのコメントをありがとう。多くのクラスを生成するケースがあり、その大部分は(バイトコードレベルで)同じクラス名を共有する可能性があります。それがUnsafe APIを選択した理由です。私の質問のポイントは ''/''の後に追加された16進文字列ではなく、 ''/''の前の文字列にあります。正しいクラス名は、 "DYNGuardWithTestHandle73/..."ではなく "DYNGuardWithTestHandle70/..."でなければなりません。 –

+0

@shijiexuバイトコードを生成するソースを含むあなたのケースの完全な画像を見ることなく、生成されたクラスをロードするためのソース。並行性の問題があるかどうか。可能であれば、完全な検証可能な例を作成してください。 – apangin

+0

@shijiexu Unsafe APIを使用する理由はまだ不明です。独自のクラス名を自分で生成することも、異なるクラスローダーによってクラスをロードすることもできます。 – apangin

関連する問題