开发者

How to intercept all read and write access to objects at runtime?

开发者 https://www.devze.com 2023-02-05 17:15 出处:网络
I am working on an aging Java \"Swing\" application that, unfortunately, uses a non Thread-safe data model. As the number of clients with multi-threading and multi-core PCs grows, so does the number o

I am working on an aging Java "Swing" application that, unfortunately, uses a non Thread-safe data model. As the number of clients with multi-threading and multi-core PCs grows, so does the number of spurious random errors due to non synchronized access to the data. We have a huge code-base, something like 6000 Java files, most of which are quite large and complicated.

I would like to create a global static ReentrantReadWriteLock to control access to the model. My plan would be to create a dummy ReadWriteLock implementation, which always succeeds and does not do anything, and use it on the productive system, while using the ReentrantReadWriteLock on the test systems, so that the transition can be gradual.

What I need is a way to "intercept" all accesses to the model in the test systems and log an error if the access is not within the scoop o开发者_如何学编程f an appropriate lock/unlock block. ReentrantReadWriteLock can tell you if you own a write lock. I am assuming I could track the read lock state myself by using a ThreadLocal or something.

So now comes the real question: How could I, in Java, write code that would intercept at runtime any access to any public method in a well-defined set of classes, and check if the access is within a lock/unlock block, by querying the global lock? Can this be done with AspectJ? Or anything else? And how?


You might find java proxies useful.
You can't add invokation handlers to existing object, but you may 'wrap' instance of your class in a proxy. Created proxy object will still be of MyClass type.


I assume it can be done with AspectJ But I haven't used it enough to know how.

Instead what I would do is use a modified copy of the classes you want to trap and add them to the bootclasspath. e.g. change a copy of FileInputStream and FileOutputStream.

For test systems this work very well in a simple manner. I wouldn't sugegst you do this in production.


I don't know how applicable this is to your situation but the best way to intercept method calls is by using dynamic proxies. For this you have to create interfaces for your classes though, which you might have done anyway.

Here's an example of how dynamic proxies work:

 interface Foo {
    void setBar( String bar );
    String getBar();
 }

 class FooImpl implements Foo {
    private String bar;
    // getter and setter
 }

This is your normal code. Now what you can do is instead of new FooImpl() you can use a proxy. For the proxy you need an [InvocationHandler][1] first.

 class LockHandler implements InvocationHandler {

    private FooImpl originalOb;

    public LockHandler( FooImpl originalOb ) {
      this.originalOb = originalOb;
    }

    @Override
    public Object invoke( Object proxy, Method method, Object [] args ) {
      try {
        if( method.getName().startsWith( "set" ) {
           // do locking stuff
        }
        return method.invoke( originalOb, args ); //invoke underlying method
      } finally {
        if( method.getName().startsWith( "set" ) {
           // do post-call locking stuff
        }
      }     
    }
 }

And then you finally create your Proxy object:

 Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                      new Class[] { Foo.class },
                                      new LockHandler( new FooImpl() ) );

Now every call to your foo object will be channeled into your invocation handler. Of course you don't have to create a new invocation handler instance for every object, you don't even need a separate one for every interface, originalOb could (and in real life should) be declared as Object type.

Another option is to use an aspect implementation, like AspectJ, which is probably simpler to use but it may be too late to introduce it, depending on how far you're into the development of the software.

0

精彩评论

暂无评论...
验证码 换一张
取 消