2016-07-13 1 views
0

5つのクラスを含むjarファイルがあります。私はそのクラスの一つのロジックを変更したいだけです。ソースパッケージ別に既存のクラス定義を更新する

BaseClassは私が修正する必要があるものです。以下の基本構造をご確認ください。 changeMeメソッドでは、1行を削除して3行追加するだけです。

私はクラスがそのクラスのオプションを拡張し、publicコンストラクタを持っていない

  1. しようとしたどのようなクラス構造が

    package com.temp; 
    
    public class BaseClass{ 
        public interface IClassA{ String sayRaw(String raw); } 
        private BaseClass(){} 
        protected static class ClassToFix extends ClassParent { 
         @Override public void changeMe() { 
           ........ 
         } 
        } 
    } 
    
    
    //---------Source from jar file-------------- 
    package com.temp; 
    
    public class ClassA implements IClassA{ 
        public static final BaseClass.IClassA ABC = ....; 
        String sayRaw(String raw){ 
        } 
    
    } 
    

    出ています。

  2. bytebuddyからメソッド・インターセプターを試しましたが、同じ問題が発生しました。
  3. 最後に私はjavaassistを試しました。 jarファイルのメソッド定義を更新していないため、動作しません。

srcディレクトリに同じパッケージを作成し、クラス定義をコピーして修正を加えました。この修正は動的Webプロジェクトでは機能しますが、Maven Javaプロジェクトでは機能しません。リンケージエラーを示しています

ClassA is implementation of interface (IClassA) from BaseClass which is the modified source.

java.lang.LinkageError: loader constraint violation: when resolving field "ABC" the class loader (instance of org/springframework/boot/devtools/restart/classloader/RestartClassLoader) of the referring class, com/temp/ClassA, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for the field's resolved type, com/temp/BaseClass$IClassA, have different Class objects for that type

これを修正する方法が他にもある場合は、私に教えてください。

+1

クラスパスに同じクラスの異なるバージョンを持つことは、おそらく面倒です。私の推奨は、必要な変更を加えて5つのクラスをすべて再コンパイルし、それらをjarして、あなたのjarだけを使うことです。 –

+0

クラスのソースをクローンし、クラスをArilillianのようなものを使用して(または、私たち自身を展開で自分自身を解凍しているように)、それを配送するjarファイルから取り出します。私は*本当にこれをお勧めしませんが...それは動作します – xenoterracide

+0

あなたがこのクラスをどのように使用しているのか、そしてなぜあなたが "モンキーパッチ"それを必要とするかに応じて他のオプションがあるかもしれません – xenoterracide

答えて

0

コンパイル時に作成できないクラスを実行時に作成することはできません。 JVMは、クラスをロードする前にクラスを検証し、試行を許可しません。

Byte BuddyまたはJavassistを使用すると、起動時に追加できるいわゆるJavaエージェントを定義できます。そうすることで、最初にロードされたときにClassToFixを再定義することができます。

バイトバディには、AgentBuilder抽象化が含まれているため、実装が比較的簡単です。 tutorials on how to implement an agent onlineが見つかります。 JavassistはJavaエージェントを定義するメカニズムを提供しませんが、独自のClassFileTransformerを作成するときにクラスを再定義することができます。

+0

あなたの答えをありがとう。あなたが言ったものと実際に似て、私は今やっている。私は新しいクラスプールを作成し、そのクラスにjarファイルを追加し、バイトコードを変更しようとしています。時にはうまくいきます。デバッグモードで動作していて、実行モードでは動作していませんでした。それはとても有線の男です。あなたはそれについて考えていますか? –

+0

エージェントを非同期で接続している可能性があります。この場合、クラスがロードされた後にエージェントが接続されている場合は、明示的に再定義する必要があります( 'Instrumentation :: retransformClasses')。それ以外の場合、クラスは計測されません。 –

0

あなたは側面を試しましたか? Aspectは、非最終クラスのオブジェクトのプロキシを作成します(私はそれがプライベートコンストラクタで動作するかどうかはわかりません)。また、どのメソッドに対してもリクエストをインターセプトできます。したがって、カスタムロジックを記述することができます。

+0

私は側面を使用する場合、オブジェクトを呼び出し側に渡す必要があります。それは私の問題のためにうまくいかないでしょう。 –

関連する問題