2016-07-13 27 views
0

我有一個包含5個類的jar文件。我只想改變那個班的一個邏輯。通過源碼包更新現有的類定義

BaseClass是我需要修復的一個。請檢查以下基本結構。 我只需要刪除一行並在changeMe方法中添加3行。

類結構

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){ 
    } 

} 

我試了一下

  1. 該類沒有公共構造函數,所以擴展類的選項出來了。
  2. 我嘗試了bytebuddy的方法攔截器,發生了同樣的問題。
  3. 最後我嘗試了javaassist。它也不起作用,因爲它不是更新jar文件中的方法定義。

我在我的src目錄中創建了相同的包,並複製了類定義並添加了我的修補程序。此修補程序在Dynamic 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

在你的類路徑中使用同一個類的不同版本是很麻煩的。我的建議是用任何需要的修改重新編譯所有五個類,並將它們打開,並僅使用你的jar。 –

+0

克隆類的來源,然後將該類從運輸它的jar中提取出來,也許使用類似arquillian的東西(或者像我們通過在部署中解壓自己的jar一樣)。我不*真的*推薦這個,但是......它的工作原理 – xenoterracide

+0

根據你如何使用這個課程以及爲什麼你需要「猴子補丁」它可能有其他選項 – xenoterracide

回答

0

您不能在編譯時創建一個在運行時不允許創建的類。 JVM在加載它之前驗證任何類,並將不允許你嘗試。

使用Byte Buddy或Javassist,您可以定義一個所謂的Java代理,您可以在啓動時添加它。這樣做時,您可以在第一次加載時重新定義ClassToFix

Byte Buddy包含一個AgentBuilder抽象,這使得這很容易實現。你可以找到tutorials on how to implement an agent online。 Javassist不提供定義Java代理的機制,但它允許您在創建自己的ClassFileTransformer時重新定義類。

+0

感謝您的回答。實際上與你所說的相似,我現在正在做。我正在創建新的類池,並將jar添加到其中並嘗試更改字節碼。有時候有時候,有時候不會。它在調試模式下工作,而不是在運行模式下工作。它是如此有線的人。你有什麼想法嗎? –

+0

您可能異步地連接代理。在這種情況下,如果代理在加載類後附加,則必須顯式重新定義它('Instrumentation :: retransformClasses')。否則,班級沒有裝備。 –

0

您是否嘗試過方面? Aspect爲任何非final類的對象創建代理(但我不確定它是否可以與私有構造函數一起使用),並允許您攔截請求到任何方法。所以你可以編寫自定義邏輯。

+0

如果我使用方面,我需要把對象給調用方。這不會解決我的問題。 –

相關問題