Matt Bastress
unread,Apr 1, 2008, 4:12:50 PM4/1/08Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to google-guice
We have been using Guice for method interception and have occasionally
encountered a bug that causes the wrong method to be invoked by the
method proxy. This either results in a ClassCastException or, in the
case of methods with compatible parameters, executing the wrong
method.
We tracked it down to MethodProxy.invokeSuper() in the version of
cglib that Guice uses (2.2_beta1). It is reproducible using multi-
threaded unit tests or in the debugger.
In invokeSuper(), threads race to do the init() and invoke the proxied
method:
if (f2 == null)
init();
return f2.invoke(i2, obj, args);
Because the first thread to init() initializes members in this order
(and not atomically):
f1 = helper(ci, ci.c1);
f2 = helper(ci, ci.c2);
i1 = f1.getIndex(sig1);
i2 = f2.getIndex(sig2);
the second thread in invokeSuper() can find that f2 is not null, and
call f2.invoke() with i2 == 0. This causes the wrong method to be
invoked.
Our fix was to initialize those four fields in init() as a single
volatile invariant and use the double-checked locking with volatile
that is safe with Java 5 and above.
I can make this fix available if anyone wants it.