[jboss-jira] [JBoss JIRA] (JASSIST-189) Bridge methods are proxied instead of desired methods
Donnchadh Ó Donnabháin (JIRA)
jira-events at lists.jboss.org
Tue Jan 8 01:04:08 EST 2013
[ https://issues.jboss.org/browse/JASSIST-189?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12743976#comment-12743976 ]
Donnchadh Ó Donnabháin commented on JASSIST-189:
------------------------------------------------
The first {{hash.put(key, oldMethod)}} is part of the existing code to prevent (or rather undo) replacing a method with with one of lower visibility.
The new code in the patch undoes the situation where we have just replaced a non-bridge method with a bridge method.
The idea is that if we are going to pick one method, it should be the non-bridge method since the bridge method will call the non-bridge method in any case.
The following is the entire patched method:
{code:title=ProxyFactory.java}
private static void getMethods(HashMap hash, Class clazz, Set visitedClasses) {
// This both speeds up scanning by avoiding duplicate interfaces and is needed to
// ensure that superinterfaces are always scanned before subinterfaces.
if (!visitedClasses.add(clazz))
return;
Class[] ifs = clazz.getInterfaces();
for (int i = 0; i < ifs.length; i++)
getMethods(hash, ifs[i], visitedClasses);
Class parent = clazz.getSuperclass();
if (parent != null)
getMethods(hash, parent, visitedClasses);
Method[] methods = SecurityActions.getDeclaredMethods(clazz);
for (int i = 0; i < methods.length; i++)
if (!Modifier.isPrivate(methods[i].getModifiers())) {
Method m = methods[i];
// JIRA JASSIST-127 (covariant return types).
String key = m.getName() + ':' + RuntimeSupport.makeDescriptor(m.getParameterTypes(), null);
// JIRA JASSIST-85
// put the method to the cache, retrieve previous definition (if any)
Method oldMethod = (Method)hash.put(key, methods[i]);
// check if visibility has been reduced
if (null != oldMethod && Modifier.isPublic(oldMethod.getModifiers())
&& !Modifier.isPublic(methods[i].getModifiers()) ) {
// we tried to overwrite a public definition with a non-public definition,
// use the old definition instead.
hash.put(key, oldMethod);
} else if (null != oldMethod && !oldMethod.isBridge() && methods[i].isBridge()
&& oldMethod.getDeclaringClass() == methods[i].getDeclaringClass()) {
hash.put(key, oldMethod);
}
}
}
{code}
> Bridge methods are proxied instead of desired methods
> -----------------------------------------------------
>
> Key: JASSIST-189
> URL: https://issues.jboss.org/browse/JASSIST-189
> Project: Javassist
> Issue Type: Bug
> Affects Versions: 3.17.1-GA
> Environment: OS X, Java 1.7.0_09
> Reporter: Donnchadh Ó Donnabháin
> Assignee: Shigeru Chiba
>
> The following test intermittently fails:
> {code}
> package org.javassist.test.covariantproxy;
> import java.lang.reflect.Method;
> import javassist.util.proxy.MethodHandler;
> import javassist.util.proxy.ProxyFactory;
> import javassist.util.proxy.ProxyObject;
> import junit.framework.TestCase;
> public class CovariantProxyTest extends TestCase {
>
> public interface TestProxy {
>
> }
>
> public static class TestMethodHandler implements MethodHandler {
>
> boolean invoked = false;
> public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
> invoked = true;
> return proceed.invoke(self, args);
> }
>
> public boolean wasInvoked() {
> return invoked;
> }
> public void reset() {
> invoked = false;
> }
> }
> public static class Issue {
>
> private Integer id;
>
> public Integer getId() {
> return id;
> }
>
> public void setId(Integer id) {
> this.id = id;
> }
> }
>
> public static class PublishedIssue extends Issue {
>
> }
> public static abstract class Article {
>
> private Integer id;
>
> public Integer getId() {
> return id;
> }
>
> public void setId(Integer id) {
> this.id = id;
> }
>
> public abstract Issue getIssue();
> }
> public static class PublishedArticle extends Article {
>
> private PublishedIssue issue;
>
> @Override
> public PublishedIssue getIssue() {
> return issue;
> }
>
> public void setIssue(PublishedIssue issue) {
> this.issue = issue;
> }
>
> }
>
> public void testThatCallingAMethodWithCovariantReturnTypeCallsProxy() throws Exception {
> Class persistentClass = PublishedArticle.class;
> ProxyFactory factory = new ProxyFactory();
> factory.setUseCache(false);
> factory.setSuperclass(persistentClass);
> factory.setInterfaces(new Class[] {TestProxy.class});
> Class cl = factory.createClass();
> TestProxy proxy = ( TestProxy ) cl.newInstance();
> TestMethodHandler methodHandler = new TestMethodHandler();
> ( ( ProxyObject ) proxy ).setHandler( methodHandler );
>
> ((Article)proxy).getIssue();
> assertTrue(methodHandler.wasInvoked());
>
> methodHandler.reset();
>
> PublishedArticle article = (PublishedArticle) proxy;
>
> article.getIssue();
>
> assertTrue(methodHandler.wasInvoked());
>
> }
>
> }
> {code}
> Were there tests added for JASSIST-24 ? I don't see any associated source.
> This bug causes a problem in hibernate, described in https://hibernate.onjira.com/browse/HHH-7884 .
> This may be related to JASSIST-162 but the circumstances are slightly different.
> The problem occurs intermittently so it appears to depend on the order in which the methods are processed.
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the jboss-jira
mailing list