[
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)