1    课堂解析

2    代码演练

2.1  枚举类单例解决序列化破坏demo

2.2  枚举类单例解决序列化破坏原理

2.3  枚举类单例解决反射攻击demo

2.4  枚举类单例解决反射攻击原理

3    jad的使用

3.1  网址:

1    课堂解析
2    代码演练
2.1  枚举类单例解决序列化破坏demo

枚举类:

package com.geely.design.pattern.creational.singleton;

/**
* 这个类是enum类型
*/
public enum EnumInstance {
INSTANCE;
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
/**
* Java类中的静态变量在程序运行期间,其内存空间对所有该类的对象实例而言是共享的,有些时候可以认为是全局变量。
* 因此在某些时候为了节省系统内存开销、共享资源,可以将类中的一些变量声明为静态变量!
*
* 最最主要的原因,单例模式外部类不能new出对象,要使用该方法只能是静态的
*
* 最终返回的肯定是本类,所以该方法的类型为EnumInstance
*/
public static EnumInstance getInstane(){
return INSTANCE;
} }

测试类:

package com.geely.design.pattern.creational.singleton;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; public class Test {
/**
* 序列化代码演练
* 将 HungrySingleton对象放入文件,再从文件读取该对象,还是同一个对象吗?
* 实际应用:在从文件存入后读取,用equals时需要注意(equals比较的是hash码)
*
* @param args
*/
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
try {
//将singleton对象写入到输出流中
EnumInstance instance = EnumInstance.getInstane();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
oos.writeObject(instance); //从输入流中读取到该对象
File file = new File("singleton_file");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
EnumInstance instance2 = (EnumInstance) ois.readObject();
System.out.println(instance);
System.out.println(instance2);
System.out.println(instance == instance2);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} }
}

打印日志:

"C:\Program Files\Java\jdk1.7.0_79\bin\java.exe" "-javaagent:D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\lib\idea_rt.jar=42967:D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;F:\xiangmu3\Xin\Idea\design_pattern\target\classes" com.geely.design.pattern.creational.singleton.Test
INSTANCE
INSTANCE
true Process finished with exit code 0
2.2  枚举类单例解决序列化破坏原理

ObjectInputStream

/**
* Underlying readObject implementation.
*/
private Object readObject0(boolean unshared) throws IOException {
boolean oldMode = bin.getBlockDataMode();
if (oldMode) {
int remain = bin.currentBlockRemaining();
if (remain > 0) {
throw new OptionalDataException(remain);
} else if (defaultDataEnd) {
/*
* Fix for 4360508: stream is currently at the end of a field
* value block written via default serialization; since there
* is no terminating TC_ENDBLOCKDATA tag, simulate
* end-of-custom-data behavior explicitly.
*/
throw new OptionalDataException(true);
}
bin.setBlockDataMode(false);
} byte tc;
while ((tc = bin.peekByte()) == TC_RESET) {
bin.readByte();
handleReset();
} depth++;
try {
switch (tc) {
case TC_NULL:
return readNull(); case TC_REFERENCE:
return readHandle(unshared); case TC_CLASS:
return readClass(unshared); case TC_CLASSDESC:
case TC_PROXYCLASSDESC:
return readClassDesc(unshared); case TC_STRING:
case TC_LONGSTRING:
return checkResolve(readString(unshared)); case TC_ARRAY:
return checkResolve(readArray(unshared));
           /*
                 * 注意:读取enum
                 *
                 */
case TC_ENUM:
return checkResolve(readEnum(unshared));
case TC_OBJECT:
return checkResolve(readOrdinaryObject(unshared)); case TC_EXCEPTION:
IOException ex = readFatalException();
throw new WriteAbortedException("writing aborted", ex); case TC_BLOCKDATA:
case TC_BLOCKDATALONG:
if (oldMode) {
bin.setBlockDataMode(true);
bin.peek(); // force header read
throw new OptionalDataException(
bin.currentBlockRemaining());
} else {
throw new StreamCorruptedException(
"unexpected block data");
} case TC_ENDBLOCKDATA:
if (oldMode) {
throw new OptionalDataException(true);
} else {
throw new StreamCorruptedException(
"unexpected end of block data");
} default:
throw new StreamCorruptedException(
String.format("invalid type code: %02X", tc));
}
} finally {
depth--;
bin.setBlockDataMode(oldMode);
}
} /**
* Reads in and returns enum constant, or null if enum type is
* unresolvable. Sets passHandle to enum constant's assigned handle.
*/
private Enum readEnum(boolean unshared) throws IOException {
if (bin.readByte() != TC_ENUM) {
throw new InternalError();
} ObjectStreamClass desc = readClassDesc(false);
if (!desc.isEnum()) {
throw new InvalidClassException("non-enum class: " + desc);
} int enumHandle = handles.assign(unshared ? unsharedMarker : null);
ClassNotFoundException resolveEx = desc.getResolveException();
if (resolveEx != null) {
handles.markException(enumHandle, resolveEx);
} String name = readString(false);//通过readString方法获取到枚举对象的名称
Enum en = null;
Class cl = desc.forClass();
if (cl != null) {
try {
en = Enum.valueOf(cl, name);//通过类型和名称获取到枚举常量,枚举中的name是唯一的,并且对应一个枚举常量,所以拿到的肯定是唯一的对象。
} catch (IllegalArgumentException ex) {
throw (IOException) new InvalidObjectException(
"enum constant " + name + " does not exist in " +
cl).initCause(ex);
}
if (!unshared) {
handles.setObject(enumHandle, en);
}
} handles.finish(enumHandle);
passHandle = enumHandle;
return en;
}
2.3  枚举类单例解决反射攻击demo

枚举类:(同2.1)

package com.geely.design.pattern.creational.singleton;

/**
* 这个类是enum类型
*/
public enum EnumInstance {
INSTANCE;
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
/**
* Java类中的静态变量在程序运行期间,其内存空间对所有该类的对象实例而言是共享的,有些时候可以认为是全局变量。
* 因此在某些时候为了节省系统内存开销、共享资源,可以将类中的一些变量声明为静态变量!
*
* 最最主要的原因,单例模式外部类不能new出对象,要使用该方法只能是静态的
*
* 最终返回的肯定是本类,所以该方法的类型为EnumInstance
*/
public static EnumInstance getInstane(){
return INSTANCE;
} }

测试类:

package com.geely.design.pattern.creational.singleton;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; public class Test { /**
* 序列化代码演练
* 将 HungrySingleton对象放入文件,再从文件读取该对象,还是同一个对象吗?
* 实际应用:在从文件存入后读取,用equals时需要注意(equals比较的是hash码)
*
* @param args
*/
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
/*try {
//将singleton对象写入到输出流中
EnumInstance instance = EnumInstance.getInstane();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
oos.writeObject(instance); //从输入流中读取到该对象
File file = new File("singleton_file");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
EnumInstance instance2 = (EnumInstance) ois.readObject();
System.out.println(instance);
System.out.println(instance2);
System.out.println(instance == instance2);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}*/ Class objectClass = EnumInstance.class;
Constructor constructor = objectClass.getDeclaredConstructor();
constructor.setAccessible(true
);
}
}

打印结果:

"C:\Program Files\Java\jdk1.7.0_79\bin\java.exe" "-javaagent:D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\lib\idea_rt.jar=43086:D:\java\devolopKit\idea\anZh\IntelliJ IDEA Community Edition 2018.1.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;F:\xiangmu3\Xin\Idea\design_pattern\target\classes" com.geely.design.pattern.creational.singleton.Test
Exception in thread "main" java.lang.NoSuchMethodException: com.geely.design.pattern.creational.singleton.EnumInstance.<init>()
at java.lang.Class.getConstructor0(Class.java:2892)
at java.lang.Class.getDeclaredConstructor(Class.java:2058)
at com.geely.design.pattern.creational.singleton.Test.main(Test.java:148
) Process finished with exit code 1

反射有参对象:

package com.geely.design.pattern.creational.singleton;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; public class Test {
/**
* 序列化代码演练
* 将 HungrySingleton对象放入文件,再从文件读取该对象,还是同一个对象吗?
* 实际应用:在从文件存入后读取,用equals时需要注意(equals比较的是hash码)
*
* @param args
*/
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
/*try {
//将singleton对象写入到输出流中
EnumInstance instance = EnumInstance.getInstane();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
oos.writeObject(instance); //从输入流中读取到该对象
File file = new File("singleton_file");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
EnumInstance instance2 = (EnumInstance) ois.readObject();
System.out.println(instance);
System.out.println(instance2);
System.out.println(instance == instance2);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}*/ Class objectClass = EnumInstance.class;
Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class);
constructor.setAccessible(true);
EnumInstance enumInstance = (EnumInstance) constructor.newInstance("dd",123); }
}

打印结果:

Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects
at java.lang.reflect.Constructor.newInstance(Constructor.java:521)
at com.geely.design.pattern.creational.singleton.Test.main(Test.java:150
) Process finished with exit code 1
2.4  枚举类单例解决反射攻击原理

Enum.java

只有有参构造器

    protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}

Constructor.java

  /**
* Uses the constructor represented by this {@code Constructor} object to
* create and initialize a new instance of the constructor's
* declaring class, with the specified initialization parameters.
* Individual parameters are automatically unwrapped to match
* primitive formal parameters, and both primitive and reference
* parameters are subject to method invocation conversions as necessary.
*
* <p>If the number of formal parameters required by the underlying constructor
* is 0, the supplied {@code initargs} array may be of length 0 or null.
*
* <p>If the constructor's declaring class is an inner class in a
* non-static context, the first argument to the constructor needs
* to be the enclosing instance; see section 15.9.3 of
* <cite>The Java&trade; Language Specification</cite>.
*
* <p>If the required access and argument checks succeed and the
* instantiation will proceed, the constructor's declaring class
* is initialized if it has not already been initialized.
*
* <p>If the constructor completes normally, returns the newly
* created and initialized instance.
*
* @param initargs array of objects to be passed as arguments to
* the constructor call; values of primitive types are wrapped in
* a wrapper object of the appropriate type (e.g. a {@code float}
* in a {@link java.lang.Float Float})
*
* @return a new object created by calling the constructor
* this object represents
*
* @exception IllegalAccessException if this {@code Constructor} object
* is enforcing Java language access control and the underlying
* constructor is inaccessible.
* @exception IllegalArgumentException if the number of actual
* and formal parameters differ; if an unwrapping
* conversion for primitive arguments fails; or if,
* after possible unwrapping, a parameter value
* cannot be converted to the corresponding formal
* parameter type by a method invocation conversion; if
* this constructor pertains to an enum type.
* @exception InstantiationException if the class that declares the
* underlying constructor represents an abstract class.
* @exception InvocationTargetException if the underlying constructor
* throws an exception.
* @exception ExceptionInInitializerError if the initialization provoked
* by this method fails.
*/
@CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)//如果目标类是枚举类型,抛出异常
throw new IllegalArgumentException("Cannot reflectively create enum objects");
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
ca = acquireConstructorAccessor();
}
return (T) ca.newInstance(initargs);
3    jad的使用
 3.1  网址:

https://varaneckas.com/jad/

设计模式课程 设计模式精讲 8-8 单例设计模式-Enum枚举单例、原理源码解析以及反编译实战的更多相关文章

  1. 【趣味设计模式系列】之【代理模式3--Cglib动态代理源码解析】

    1. 图解 上图主要描述了Cglib动态代理的主要执行过程,下面做详细分析,以下源码使用的Cglib版本为3.2.12. 2. Enhancer源码分析 public Object create() ...

  2. 【趣味设计模式系列】之【代理模式2--JDK动态代理源码解析】

    1. 图解 上图主要描述了JDK动态代理的执行过程,下面做详细分析. 2. Proxy源码分析 上一篇,在使用JDK动态代理的时候,借助于Proxy类,使用newProxyInstance静态方法,创 ...

  3. 【设计模式】Java设计模式精讲之原型模式

    简单记录 - 慕课网 Java设计模式精讲 Debug方式+内存分析 & 设计模式之禅-秦小波 文章目录 1.原型模式的定义 原型-定义 原型-类型 2.原型模式的实现 原型模式的通用类图 原 ...

  4. 设计模式课程 设计模式精讲 7-2 建造者模式Coding

    1 代码演练 1.1 建造者模式演练 1.2 静态内部类演练建造者模式(链式调用) 1 代码演练 1.1 建造者模式演练 需求: 根据讲师提供的课程名称,课程ppt,课程视频,课程手记,课程问答 制作 ...

  5. 设计模式课程 设计模式精讲 17-2 模板方法模式coding

    1 代码演练 1.1 代码演练1 1.2 代码演练2(后端课程子类运用钩子方法,加入写手记的方法) 1.3 代码演练3(前端有多个子类,有得需要写手记,有得不需要写,如何实现?) 1 代码演练 1.1 ...

  6. 设计模式课程 设计模式精讲 8-11 单例模式源码解析(jdk+spring+mybaties)

    1 源码解析 1.1 单例解析1 1.2 单例解析2(容器单例) 1.3 单例解析3 1.4 单例解析4 1 源码解析 1.1 单例解析1 java.lang.Runtime /** * 饿汉式加载, ...

  7. Java设计模式精讲之UML急速入门

    简单记录 - 慕课网 - Java设计模式精讲 Debug方式+内存分析 文章目录 第2章 UML急速入门 2-1.UML简单入门 UML定义 UML特点 UML 2.2分类 UML类图 理解泛化.实 ...

  8. iOS开发之单例设计模式(完整正确版本)

    单例的意思从字面上就可以略知一二,所谓单例就是确保在程序运行过程中只创建一个对象实例.可以用于需要被多次广泛或者说多次使用的资源中,比如我们常见的网络请求类.工具类以及其它管理类等.比如我iOS开发中 ...

  9. JAVA_SE基础——38.单例设计模式

    本文继续介绍23种设计模式系列之单例模式. 我们在javaSE的基础学习中,会讲到:单例设计模式.模板设计模式.装饰者设计模式.观察者设计模式.工厂设计模式 我以后随着水平的提高,我会专门开个分类写设 ...

随机推荐

  1. Hyperledger Explorer

    简介 Hyperledger Explorer is a simple, powerful, easy-to-use, well maintained, open source utility to ...

  2. python中的坎坷之函数、集合

    函数 作用:实现一个功能,函数理解成一个工具,遇到问题把这个工具拿来用 优点:函数更方便,复用,可以在多个场景下用 1.带参数的函数 name='lzs-nice' nane.split('-') # ...

  3. js把树形数据转成扁平数据

    我就直接上代码了都是实际项目里面用到的 1.假设这个json就已经是树型结构数据了(如果不知道怎么实现树型结构数据请看我另一篇博客) var compressedArr=afcommon.treeDa ...

  4. 控制反转(IOC)和依赖注入(DI)

    控制反转(IOC)和依赖注入(DI)IoC(Inversion of Control,控制反转) 是Spring 中一个非常非常重要的概念,它不是什么技术,而是一种解耦的设计思想.它的主要目的是借助于 ...

  5. PL2303HXA自2012已停产

    解决"PL2303HXA自2012已停产,请联系供货商" USB不识别的问题: 问题是WIN10自带的驱动不兼容引起的,只能安装早期驱动,再驱动程序中选择旧版本驱动即可

  6. 安卓之文本视图TextView及跑马灯效果

    一.基本属性和设置方法 二.跑马灯用到的属性与方法说明 三.省略方式的取值说明 四.跑马灯效果案例代码   (1)布局xml文件 <?xml version="1.0" en ...

  7. Could not transfer artifact org.springframework.boot:spring-boot-starter-parent:pom:2.1.9.RELEASE from/to 阿里云镜像地址

    今天从 http://start.spring.io/ 下载的demo项目,导入eclipse后,pom文件一直报 parent包错,然后感觉就是自己maven镜像里面搜不到这个包, 所以改了 mav ...

  8. django的静态文件配置和路由控制

    上一篇写到刚建完django项目,此时我登录页面中调用了js文件,执行后发现报错了找不到js这个文件 目录结构如图所示: <!DOCTYPE html> <html lang=&qu ...

  9. JS中的 '+' 号

    当用作单目操作符的时候,+操作符不会对Number类型产生影响.但如果应用在字符串类型上,会将其转换为数字: var a = 25;a =+ a; //对a值没有影响console.log(a); / ...

  10. 最新版自动检测卡片类型工具软件版本(auto check card type v3.2.0)

    自动检测卡片类型工具软件. 卡片放到读卡器上面自动识别卡片类型,不需老是按下按钮,好用,方便.支持自动识别NTAG213卡片,NTAG215卡片, NTAG216卡片,Ultralight芯片, Ul ...