java 构造函数抛出异常_java – 使构造函数抛出异常是一种好习惯吗?

准则7-3 / OBJECT-3:防止部分初始化   非final类的实例当非final类中的构造函数时   抛出异常,攻击者可以尝试部分获取访问权限   初始化该类的实例。 确保非最终类   在构造函数成功完成之前,它仍然完全无法使用。

从JDK 6开始,可以防止构造可子类化的类   通过在Object构造函数完成之前抛出异常。 至   执行此操作,在a中计算的表达式中执行检查   调用this()或super()。

publicabstractclassClassLoader{privatefinalClassLoaderImplimpl;protectedClassLoader(){this.impl=newClassLoaderImpl();}protectedfinalClassdefineClass(…){returnimpl.defineClass(…);}}/* pp */classClassLoaderImpl{/* pp */ClassLoaderImpl(){// permission needed to create ClassLoadersecurityManagerCheck();init();}/* pp */ClassdefineClass(…){// regular logic follows…}}”>//非最终的java.lang.ClassLoader     公共抽象类ClassLoader {         protected ClassLoader(){            此(securityManagerCheck());        }         private ClassLoader(Void被忽略){             // …继续初始化…        }         private static Void securityManagerCheck(){             SecurityManager security = System.getSecurityManager();             if(security!= null){                security.checkCreateClassLoader();            }             return null;        }    }

为了与旧版本兼容,潜在的解决方案涉及到   使用初始化标志。 将标志设置为最后一次操作   成功返回之前的构造函数。 提供的所有方法   敏感操作的网关必须先咨询该标志  程序:

publicabstractclassClassLoader{privatefinalClassLoaderImplimpl;protectedClassLoader(){this.impl=newClassLoaderImpl();}protectedfinalClassdefineClass(…){returnimpl.defineClass(…);}}/* pp */classClassLoaderImpl{/* pp */ClassLoaderImpl(){// permission needed to create ClassLoadersecurityManagerCheck();init();}/* pp */ClassdefineClass(…){// regular logic follows…}}”>公共抽象类ClassLoader {         private volatile boolean initialized;         protected ClassLoader(){             //创建ClassLoader所需的权限            securityManagerCheck();             在里面();             //构造函数的最后一个动作。             this.initialized = true;        }         protected final类defineClass(…){            checkInitialized();             //遵循常规逻辑            …        }         private void checkInitialized(){             if(!initialized){                 抛出新的SecurityException(                     “非最终未初始化”                );            }        }    }

此外,应检查此类的任何安全敏感用途   初始化标志的状态。 在ClassLoader的情况下   构造时,应检查其父类加载器是否为  初始化。

可以访问非final类的部分初始化实例   通过终结者攻击。 攻击者会覆盖受保护的终结   子类中的方法,并尝试创建它的新实例  子类。 这种尝试失败了(在上面的例子中,   SecurityManager签入ClassLoader的构造函数会引发安全性   例外),但攻击者只是忽略任何异常并等待   用于虚拟机在部分上执行最终化   初始化对象。 当发生恶意终结方法时   调用实现,让攻击者访问它,a   引用正在最终确定的对象。 虽然对象是唯一的   部分初始化后,攻击者仍然可以在其上调用方法,   从而绕过SecurityManager检查。 虽然初始化了   flag不会阻止访问部分初始化的对象   确实阻止该对象上的方法对该对象执行任何有用的操作  攻击者。

使用初始化标志虽然安全,但可能很麻烦。 只是   确保公共非最终类中的所有字段都包含安全   对象初始化完成之前的值(例如null)   成功地可以在类中表示合理的替代方案   对安全性不敏感。

更强大,但也更冗长的方法是使用“指针”   实现“(或”pimpl“)。该类的核心被移入a   非公共类与接口类转发方法调用。 任何   将导致在完全初始化之前尝试使用该类   在NullPointerException中。 这种方法也适合处理   克隆和反序列化攻击。

publicabstractclassClassLoader{privatefinalClassLoaderImplimpl;protectedClassLoader(){this.impl=newClassLoaderImpl();}protectedfinalClassdefineClass(…){returnimpl.defineClass(…);}}/* pp */classClassLoaderImpl{/* pp */ClassLoaderImpl(){// permission needed to create ClassLoadersecurityManagerCheck();init();}/* pp */ClassdefineClass(…){// regular logic follows…}}”>公共抽象类ClassLoader {         private final ClassLoaderImpl impl;         protected ClassLoader(){             this.impl = new ClassLoaderImpl();        }         protected final类defineClass(…){             return impl.defineClass(…);        }    }     / * pp * / class ClassLoaderImpl {         / * pp * / ClassLoaderImpl(){             //创建ClassLoader所需的权限            securityManagerCheck();             在里面();        }         / * pp * / Class defineClass(…){             //遵循常规逻辑            …        }    }


版权声明:本文为weixin_39635657原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。