I have class file has a method like this:
public boolean validate(String str) {}
There're lots of codes inside this validat开发者_如何学JAVAe method, but I only want to make it always return true or false. Can someone point me out how to modify a class file to achieve this?
RULE override rtn CLASS Foo METHOD validate IF true DO RETURN true ENDRULE
http://www.jboss.org/byteman
Are you trying to unit test this code and force an answer without caring about the conditions? If that is the case, then you are looking for "Mocking" frameworks. In Java, I can think of Mockito and EasyMock off of the top of my head.
Relatedly, you can use PowerMock (works in tandem with either of the above Mocking frameworks) to dynamically change classes (such as final
classes/methods, static
methods, and even private
pieces of classes). PowerMock actually can change the byte code when necessary. Check under its classloading folders.
I've never considered it, but it might be possible to use any of them within non-test code, but they may require finagling to avoid JUnit dependencies (such as JUnit Runner). Again, I have never thought about it, so I never thought through the implications.
At the very least, you can probably look through PowerMockito to see how they change the byte code.
If you just want to unit test, then it's extremely easy and you probably don't need to worry about the byte code.
public class SomeClass {
public boolean validate(String s) {
// tons of logic
}
}
Test (using Mockito with JUnit 4 (drop the @Test
attribute for JUnit 3)):
private final MyClassBeingTested testClass = new MyClassBeingTested();
@Test
public void testMyCodeWithSomeClass() {
SomeClass some = mock(SomeClass.class);
when(some.validate(anyString())).thenReturn(eq(true));
// whenever it uses "some.validate()", with any
// string, then it will return true
testClass.useSomeClass(some);
// assert whatever conditions you want
// if you care to ensure that it called validate:
// note: times(1) is implied if not supplied, but times(0), times(2), etc.
// could be used ("never()" exists as a synonym for times(0))
verify(some, times(1)).validate(anyString());
}
It can only return true or false, according to the method signature provided.
Can you make a wrapper class that delegates calls to the original and overrides the behaviour that you require, instead of trying to manipulate the bytecode?
The simplest way to modify the byte code is to decompile the class or get a copy of the source code. Change the code and compile it. Put the new version earlier in the classpath or replace the original in the jar. This way you have changed the method.
You can change it at runtime, but that is 100x harder. ;)
精彩评论