[ 
https://issues.apache.org/jira/browse/IGNITE-6944?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16264090#comment-16264090
 ] 

Edmond Tsang commented on IGNITE-6944:
--------------------------------------

[~agura], [~vkulichenko],yes according to java.io.Serializable interface, we 
should search for the writeReplace/ReadResolve methods in the class being 
serialized as well as its parent classes.

Can I suggest with proposed fix below (which the logic is actually from 
java.io.ObjectStreamClass).

In org.apache.ignite.internal.binary.BinaryClassDescriptor.java, under the 
constructor BinaryClassDescriptor(), call getInheritableMethod():
{code:java}
        if (mode == BinaryWriteMode.BINARY || mode == BinaryWriteMode.OBJECT) {
                readResolveMtd = U.getInheritableMethod(cls, "readResolve");

            writeReplaceMthd = U.getInheritableMethod(cls, "writeReplace");
        }
{code}

In org.apache.ignite.internal.util.IgniteUtils.java, add below functions:
{code:java}
    /**
     * Finds inheritable method in the class and it parents.
     *
     * The logic is based on java.io.ObjectStreamClass
     *
     * @param cls The class to search,
     * @param name Name of the method.
     * @param paramTypes Method parameters.
     * @return Method or {@code null}.
     */
    @Nullable public static Method getInheritableMethod(Class<?> cls, String 
name, Class<?>... paramTypes) {
        Method meth = null;
        Class defCl = cls;
        while (defCl != null) {
                try {
                        meth = defCl.getDeclaredMethod(name, paramTypes);
                        break;
                } catch (NoSuchMethodException ex) {
                        defCl = defCl.getSuperclass();
                }
        }

        if ((meth == null) || (meth.getReturnType() == void.class)) {
                return null;
        }
        meth.setAccessible(true);
        int mods = meth.getModifiers();
        if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
                return null;
        } else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
                return meth;
        } else if ((mods & Modifier.PRIVATE) != 0) {
                return (cls == defCl) ? meth : null;
        } else {
                return packageEquals(cls, defCl) ? meth : null;
        }
    }
    
    private static boolean packageEquals(Class cl1, Class cl2) {
        return (cl1.getClassLoader() == cl2.getClassLoader() && 
                getPackageName(cl1).equals(getPackageName(cl2)));
    }

    private static String getPackageName(Class cl) {
        String s = cl.getName();
        int i = s.lastIndexOf('[');
        if (i >= 0) {
                s = s.substring(i + 2);
        }
        i = s.lastIndexOf('.');
        return (i >= 0) ? s.substring(0, i) : "";
    }
{code}

With these changes, it shouldn't break your 
[IGNITE-6485|https://issues.apache.org/jira/browse/IGNITE-6485] as it is 
passing your original unit test testWriteReplace() under 
BinaryMarshallerSelfTest.java.

Please let me know.

> Fail to execute task with immutable list string
> -----------------------------------------------
>
>                 Key: IGNITE-6944
>                 URL: https://issues.apache.org/jira/browse/IGNITE-6944
>             Project: Ignite
>          Issue Type: Bug
>          Components: binary
>    Affects Versions: 2.3
>            Reporter: Edmond Tsang
>         Attachments: BinaryMarshellerWithGuavaSelfTest.java, 
> TestClientWithGuava.java
>
>
> Exception occurs when executing task with immutable list of string due to not 
> able to find method readResolve/writeReplace for binary object.
> It appears this is caused by a side effect of Jira 
> https://issues.apache.org/jira/browse/IGNITE-6485 



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to