java反序列化

  之前介绍过java内置的序列化,今天总结下java的反序列化,主要介绍一点吧,它是怎么跳过构造函数生成对象的,当然跳过不是故意的,因为它本身实现就没依赖构造函数。比如我们定义了一个private的构造函数的bean,它序列化后的数据仍然可以反序列化出来。总之吧,反序列化不会触发构造函数的逻辑。
  反序列化时调用链:
objectInputStream.readObject()-> objectInputStream.readObject0()->objectInputStream.readOrdinaryObject()->ObjectStreamClass.newInstance()->Constructor.newInstance(),随着调用链,我们将会看到如下的调试信息:
我是图片
  然后就返回一个带类型的对象了,看不到任何调试信息,甚至不知道ca是哪个类。所以我们只能使用debug版本的jdk了。基于openjdk源码编译jdk
通过debug的jdk我们获取到ca的类型为GeneratedSerializationConstructorAccessor1,这个类是jvm运行时生成的,要看里面的信息只能dump class文件了,如何dump class文件,里面的实现很优雅,贴个简单可行的。

 sudo java -classpath "$JAVA_HOME/lib/sa-jdi.jar" -Dsun.jvm.hotspot.tools.jcore.filter=sun.jvm.hotspot.tools.jcore.PackageNameFilter -Dsun.jvm.hotspot.tools.jcore.PackageNameFilter.pkgList=sun.reflect  sun.jvm.hotspot.tools.jcore.ClassDump  <pid> 

  如果报错再试试product版本的jdk,能dump 出字节码文件就行。在当前目录就会生成一个sun包,进去就可以找到GeneratedSerializationConstructorAccessor1了。
相关字节码信息
  这个字节码文件是不能反编译为java文件的,因为它违法语言规范,但是满足字节码文件格式。里面大致的逻辑就是使用new 字节码生成一个空对象,然后调用Object的构造方法进行初始化。
  生成对象之后就是相关数据的赋值了,最后我们需要的对象。正常我们new一个对象或者通过反射构造一个对象,最终都会调用 new,invokespecial字节码指令,对于我们来说他们是一体的。new指令会在内存中开辟一块空间,invokespecial会调用构造函数,他们针对的类型都是一样的。而这里new开辟的是我们定义的类的类型,而invokespecial调用的是Object的构造函数。

参考:
不用构造方法也能够生成对象

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值