4

We have a large class (100s of methods) which has an interface annotated with lazy loading guidelines. When initially loading this object and sending it to the client we do a limited load of the most frequently used and recent data. We are currently using java Proxying to sniff on every invocation. On every invocation we are checking "Do we have the data? If there is a date param, have we loaded data for that date?" If the answer is no to either of those questions we go back to the server and load the full object.

This works, however, the java reflection, proxying, and the extra overhead on calls like basic getters (getId() for example) plays havoc on the performance of some of our code.

I want to start using byte buddy to hopefully decrease the invocation costs, especially on the simple fields that are always loaded.

What is the best way to approach this?

Also, because this object is being serialized (Java serialization, The server makes these objects and hands them off to the client), what is the right way to make sure these dynamically created classes can be passed from server to client across the wire?

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
Cogman
  • 2,070
  • 19
  • 36

1 Answers1

1

One thing you can do differently using Byte Buddy is to intercept different methods in a different way. This way, you can take the available data into consideration while creating the proxy instead of delaying this until runtime. For example:

interface Foo {

  Object simpleProperty();

  @Lazy
  Object complexProperty();

  @Lazy
  Object timedProperty(Date date);
}

You could write an interceptor that matches any of the methods:

new ByteBuddy()
  .subclass(Foo.class)
  .method(any()).
    intercept(directValueInterceptor)
  .method(isAnnotatedBy(Lazy.class))
    .intercept(lazyValueInterceptor)
  .method(isAnnotatedBy(Lazy.class).and(takesArguments(Date.class))
    .intercept(lazyTimedInterceptor)

The matchers are applied reverse in their order, meaning that a method that is annotated by Lazy and takes an argument Date is intercepted by the last interceptor while a method that is not annotated is matched by the first interceptor. This way, you can write specialized interceptors that operate on the made assumption of how to return a value and you do not longer need to introspect at runtime.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • How would you suggest I go about doing the data load? Right now, we are saving off in the proxy a partially loaded object and we are calling `Method.invoke` on that object. When a loading event happens we simply swap the partially loaded object out for a fully loaded object. – Cogman Jun 11 '15 at 13:13
  • Have a look at the `@Pipe` annotation. It allows you to avoid the boxing which normally causes the performance problems. – Rafael Winterhalter Jun 11 '15 at 13:33