13

I want to hook the method System.out.print in Java and have the ability to read/change the variables used in the method before the part of the method is called that actually adds the string to whatever the output stream is.

In C++ I would just detour the function, or set an int3 instruction so I could access the registers but in java I have no idea how to accomplish something similar.

Nowayz
  • 1,882
  • 4
  • 21
  • 34

5 Answers5

7

You can rewrite the byte code of the methods, and in the process capture/change the local variables. It is not trivial. See some notes here.

Maybe what you really want is a java debugger? You can connect a debugger to a remote process, add a breakpoint, and capture/change the local variables pretty easily using eclipse.

What is the real problem you are trying to solve?

Community
  • 1
  • 1
sbridges
  • 24,960
  • 4
  • 64
  • 71
  • Yeah this is just what I was looking for, I guess I'll have to read up on how Java bytecode works. Thanks for the helpful answer. – Nowayz May 03 '11 at 00:51
  • I'm trying to log all of the calls of System.out.print to a file. But the application that I'm running my class on isn't one that I've developed and it would be somewhat difficult to actually modify the existing code so I need some way to hook the method on a VM scale for the purpose of logging. – Nowayz May 03 '11 at 01:04
  • You can use aspects http://www.eclipse.org/aspectj/doc/released/progguide/starting-aspectj.html to add a point cut around every System.out.println, or simply set System.out to something else http://blogs.sun.com/nickstephen/entry/java_redirecting_system_out_and – sbridges May 03 '11 at 01:09
  • Will the overwriting System.out affect ALL calls to that API? even by other classes etc, so long as they're on the same VM? – Nowayz May 03 '11 at 01:19
  • yes, it will affect all calls to System.out for the entire jvm – sbridges May 03 '11 at 01:22
3

Have a look at this link.

He sneakily defines a static anonymous class so that System.out points to something different, and therefore print and println will route through that object.

Mike
  • 19,267
  • 11
  • 56
  • 72
  • Basically I'm looking for an effect that changes the method for the entire VM instance, is this possible? – Nowayz May 03 '11 at 00:47
  • 1
    I'm not sure how to do this, but I think making a Custom Class Loader for System.out would do this. Just an idea. – Mike May 03 '11 at 00:51
3

You can reassign System.out (and System.err) to another object which does what you want to do with it. Said object usually gets the old System.out value so that output can be made in the end.

This is usually done in main() and influences the whole JVM.

We use this to have automatic wrapping at 130 columns in a very peculiar setting where longer lines are truncated.

Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
0

Since JDK 1.1, the System.setOut and System.setErr methods are added to enable applications to hook the streams.

Link : http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#setOut(java.io.PrintStream)

http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#setErr(java.io.PrintStream)

minmaxavg
  • 686
  • 6
  • 21
0

@Nowayz Some time before i too had the same problem with me. After some research i came to know About AOP. AOP i.e. AspectJ provides a facility to intercept the java APIs by applying the pointcuts before,after, around. So have a look at it .You can refer my question on stack .it may help you.

Community
  • 1
  • 1
Anonymous
  • 1,726
  • 4
  • 22
  • 47