D
David C. Partridge
I want to intercept method calls on Java classes. The classes in question
are delivered by a third party in a jar file and I do not have access to the
sources for that. The client code that uses those classes is also not
available to me. If I were writing C code I'd just create a new shared
library that exported the API calls I wanted to intercept, and dynamically
load the real API calls (after adjusting the appropriate environment
variables so that my library was picked up first.
I was hoping to use java.lang.reflect.Proxy to do this, and in Tom Harpin's
article "Using java.lang.reflect.Proxy to Interpose on Java Class Methods",
he said:
===QUOTE===
At class load time, the interposed class must be found before the original
one. This can be readily accomplished through manipulation of the CLASSPATH
environment variable or a -classpath switch on the commandline. The
interposed class must have the same full name as the original. For example,
a class Foo may exist in package pub.foo and create an instance of class Bar
from package pub.bar. Creating a file Bar.java in another directory, such as
fake/pub/bar and prepending /fake to the classpath, ensures that the JVM
will load our definition of class pub.bar.Bar rather than the original. In
this way, we can interpose our definitions of Bar's methods over the
originals.
There is a problem, however, if we now wish to dispatch to the original
method. Since each classloader maintains a cache of unique class names, the
interposed and original classes pub.bar.Bar cannot coexist in the same
classloader's namespace. Therfore, the original class must be loaded by a
separate classloader (using a different classpath) and a technique must be
devised to "trampoline" from the interposed method call to the original.
===QUOTE===
and also said:
===QUOTE===
The proxy class is relatively flexible and straightforward to use, but there
are some distinct limitations on its use for method interposing. One
limitation is that the method must be called through an instance of the
proxy class. So nested methods calls, for instance, would not be
intercepted. Another limitation is that the method must have been defined in
an Interface that is implemented by the object being proxied. It can not be
called through an instance of a class that does not implement an interface.
The next article in this series will illustrate some techniques for
overcoming these limitations.
===QUOTE===
As far as I can determine, no such article was ever published. Does anyone
know of techniques that I can use to achieve the required result so that I
can intercept those method calls (preferably by just modifying CLASSPATH so
my jar file is picked up ahead of the other one).
Dave
are delivered by a third party in a jar file and I do not have access to the
sources for that. The client code that uses those classes is also not
available to me. If I were writing C code I'd just create a new shared
library that exported the API calls I wanted to intercept, and dynamically
load the real API calls (after adjusting the appropriate environment
variables so that my library was picked up first.
I was hoping to use java.lang.reflect.Proxy to do this, and in Tom Harpin's
article "Using java.lang.reflect.Proxy to Interpose on Java Class Methods",
he said:
===QUOTE===
At class load time, the interposed class must be found before the original
one. This can be readily accomplished through manipulation of the CLASSPATH
environment variable or a -classpath switch on the commandline. The
interposed class must have the same full name as the original. For example,
a class Foo may exist in package pub.foo and create an instance of class Bar
from package pub.bar. Creating a file Bar.java in another directory, such as
fake/pub/bar and prepending /fake to the classpath, ensures that the JVM
will load our definition of class pub.bar.Bar rather than the original. In
this way, we can interpose our definitions of Bar's methods over the
originals.
There is a problem, however, if we now wish to dispatch to the original
method. Since each classloader maintains a cache of unique class names, the
interposed and original classes pub.bar.Bar cannot coexist in the same
classloader's namespace. Therfore, the original class must be loaded by a
separate classloader (using a different classpath) and a technique must be
devised to "trampoline" from the interposed method call to the original.
===QUOTE===
and also said:
===QUOTE===
The proxy class is relatively flexible and straightforward to use, but there
are some distinct limitations on its use for method interposing. One
limitation is that the method must be called through an instance of the
proxy class. So nested methods calls, for instance, would not be
intercepted. Another limitation is that the method must have been defined in
an Interface that is implemented by the object being proxied. It can not be
called through an instance of a class that does not implement an interface.
The next article in this series will illustrate some techniques for
overcoming these limitations.
===QUOTE===
As far as I can determine, no such article was ever published. Does anyone
know of techniques that I can use to achieve the required result so that I
can intercept those method calls (preferably by just modifying CLASSPATH so
my jar file is picked up ahead of the other one).
Dave