如何修改或替换 java class 中的私有方法
How to modify or substitute private method in a java class
我有一个 class 我想改变的行为。我需要用另一种实现替换私有方法。常见的反射技术允许修改私有变量或调用私有方法。但是我找不到关于替换整个方法的信息。
我认为有先进的技术可以做到这一点。标准 java 反射可能是不可能的,但可能还有其他工具可以在运行时重新编译字节码。
无需采用高级技术,有一个简单的技巧即可实现。
如果您 class 是开源 jar 的一部分,请从 grepcode.com 获取此 class 文件的源代码。更改要更改的方法并编译它。并使用更新后的 class 文件更新您的 jar file/classpath。
修改替换:
一个选项是用修改后的副本屏蔽class(修改代码,重新编译代码,将修改后的class添加到class路径之前 已修补 classes),类似于 used here 检查通常不可用方法如何工作的方法。
如果您没有要修改的源代码,您可以使用 decompilers "reverse" 几乎任何 .class 文件到或多或少可读的源代码。请注意,根据许可,您可能无权这样做 and/or 以重新分发您的更改。
通过代理打补丁:
您还可以使用 -javaagent:<jarpath>[=<options>]
命令行选项修补这些方法。 "agent" 是一个 jar,可以修改加载的 classes 并改变它们的行为。 More information here.
模拟:
如果您可以控制调用方法的地方,您可以用存根版本替换目标实例。 Mockito 等库使这变得非常非常简单:
LinkedList mockedList = mock(LinkedList.class);
// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");
即使 Mockito 本身不支持模拟私有方法(主要是因为查看其他 classes 的私有方法被认为是不礼貌的),使用 PowerMock 允许您这样做(感谢, @talex).
您不能在运行时替换方法(至少不能侵入 JVM)。但是你可以替换整个 class。有几种方法可以做到这一点。例如,您可以使用名为 "aspect".
的东西
但根据我的经验,我可以说如果你需要这样做,你在开始的地方转错了方向。
或许你最好退一步,纵观全局
我有一个 class 我想改变的行为。我需要用另一种实现替换私有方法。常见的反射技术允许修改私有变量或调用私有方法。但是我找不到关于替换整个方法的信息。
我认为有先进的技术可以做到这一点。标准 java 反射可能是不可能的,但可能还有其他工具可以在运行时重新编译字节码。
无需采用高级技术,有一个简单的技巧即可实现。
如果您 class 是开源 jar 的一部分,请从 grepcode.com 获取此 class 文件的源代码。更改要更改的方法并编译它。并使用更新后的 class 文件更新您的 jar file/classpath。
修改替换:
一个选项是用修改后的副本屏蔽class(修改代码,重新编译代码,将修改后的class添加到class路径之前 已修补 classes),类似于 used here 检查通常不可用方法如何工作的方法。
如果您没有要修改的源代码,您可以使用 decompilers "reverse" 几乎任何 .class 文件到或多或少可读的源代码。请注意,根据许可,您可能无权这样做 and/or 以重新分发您的更改。
通过代理打补丁:
您还可以使用 -javaagent:<jarpath>[=<options>]
命令行选项修补这些方法。 "agent" 是一个 jar,可以修改加载的 classes 并改变它们的行为。 More information here.
模拟:
如果您可以控制调用方法的地方,您可以用存根版本替换目标实例。 Mockito 等库使这变得非常非常简单:
LinkedList mockedList = mock(LinkedList.class);
// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");
即使 Mockito 本身不支持模拟私有方法(主要是因为查看其他 classes 的私有方法被认为是不礼貌的),使用 PowerMock 允许您这样做(感谢, @talex).
您不能在运行时替换方法(至少不能侵入 JVM)。但是你可以替换整个 class。有几种方法可以做到这一点。例如,您可以使用名为 "aspect".
的东西但根据我的经验,我可以说如果你需要这样做,你在开始的地方转错了方向。
或许你最好退一步,纵观全局