http://www.dewen.io/q/9229
(仍旧不清楚是怎么回事 ,转发只当作)
谈谈自己的理解, 权作 抛砖引玉.
为什么说 "构造函数中this引用逸出的问题"
在构造函数中, this引用逸出, 则此时 可能对象实例还没有完全初始化. 比如此对象实例有final int i=47; 因为i还没有初始化, 外部线程去 查看i, 可能会看到i==null的结果. 这就不对了
说仔细一点, 初始化一个对象, 比如代码new TestClass(), 完成了以下操作
- 1).为TestClass对象实例分配内存空间;this指针指向此空间;
- 2).调用TestClass的初始化函数;在TestClass的初始化函数中;
- 2.1).首先调用TestClass的父类的初始化函数,这里是一个递归调用父类初始化函数的过程;
- 2.2).执行TestClass自身的初始化逻辑,如给对象实例成员赋初值.
所以说, 在1) 和 2.2) 之间是有 "空窗期"的, 如果这是this被外部线程拿到, 则可以看到 对象实例 未初始化的实例成员. 比如上面说的final int i == null的现象.
上面这些可以参考下面的字节码:
字节码为:
- classSup{
- Sup();
- 0 aload_0 [this]
- 1 invokespecial java.lang.Object()[8]
- 4 return
- }
- classSubextendsSup{
- finalint i;
- Sub();
- 0 aload_0 [this]
- 1 invokespecial Sup()[10]
- 4 aload_0 [this]
- 5 iconst_1
- 6 putfield Sub.i :int[12]
- 9 return
- void test();
- 0 newSub[1]
- 3 invokespecial Sub()[19]
- 6 return
- }
这里的Sub对象实例 在 Sub.test()的0行就已经 生成了, 也就是说这里this已经指向了 新生成对象实例的内存空间. 但是Sub对象实例的 final成员i, 是在Sub初始化函数的第6行才被赋值.
再说一下 具体到 JCP 的代码, "注册listener监听器,或者start()新的线程,为什么会存在this指针逸出的风险"
因为 内部类 隐式包含了 外部类的 this指针, 这个见下面的示例:
字节码:
- classOutter1{
- Outter1();
- 0 aload_0 [this]
- 1 invokespecial java.lang.Object()[8]
- 4 return
- }
- privateclassOutter1$Inner{
- final synthetic Outter1this$0;
- privateOutter1$Inner(Outter1 arg0);
- 0 aload_0 [this]
- 1 aload_1 [arg0]
- 2 putfield Outter1$Inner.this$0 :Outter1[10]
- 5 aload_0 [this]
- 6 invokespecial java.lang.Object()[12]
- 9 return
- }
重点是 内部类里 有这个:
final synthetic Outter1 this$0;
synthetic 表示这个是编译器 自己加上去的. 在内部类的初始化函数中此引用被 赋值.
相关推荐
复制构造函数引用this指针静态成员.ppt
详细介绍了构造函数、复制构造函数、拷贝构造函数之间的区别
问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。 2. 从使用角度,虚函数主要用于在信息不全的情况下,能使...
每个类都具有构造函数和析构函数。其中,构造函数在定义对象时被调用,析构函数在对象释放时被调用。如果用户没有提供构造函数和析构函数,系统将提供默认的构造函数和析构函数。 1.构造函数 构造函数是一个与类同名...
《Visual C++2012入门经典(第6版)》实例,在派生类的构造函数中调用基类的构造函数
c#析构构造函数c#析构构造函数c#析构构造函数c#析构构造函数
构造函数与默认构造函数的声明、定义、应用、比较
本程序包含构造函数和析构函数,可以把构造函数和析构函数的作用区分开
包含默认构造函数 初始化构造函数 复制构造函数 转换构造函数
构建一个类Point,它提供两个公有的构造函数,一个没有参数的Point构造函数和一个有两个double参数的构造函数。另外在该类中提供一个静态方法计算两个点的直线距离,传入参数为两个Point类实例。然后设计一个测试类...
C++ 拷贝构造函数 赋值构造函数 解释
C++中的构造函数、析构函数剖析 在C+ + 中, 构造函数是一个在构件对象的时 候调用的特殊的函数, 其目的是对对象进行初始 化工作, 从而使对象被使用之前可以处于一种合 理的状态。析构函数是在撤消对象时, 收回对象 ...
c++之十引用和拷贝构造函数c++之十引用和拷贝构造函数c++之十引用和拷贝构造函数c++之十引用和拷贝构造函数
C++ Primer中在讲构造函数初始化列表的时候有这么一段话:无论是在构造函数初始化列表中初始化成员,还是在构造函数体中对它们赋值,最终结果是相同的。不同之处在于,使用构造函数初始化列表的版本初始化数据成员,...
C++\测试 对象成员构造函数、基类构造函数、派生类本身的构造函数 的先后顺序.rar
子类如果有多个构造函数的时候,父类要么没有构造函数, 让编译器自动产生,那么在执行子类构造函数之前先执行编 译器自动产生的父类的缺省构造函数;要么至少要有一个显 式的缺省构造函数可以让子类的构造函数调用...
map使用std::map, CArray,int> > 错误, 解决: 重写CArray, 重载构造函数并加const 添加操作 operator =
C++ 默认构造函数C++ 默认构造函数C++ 默认构造函数C++ 默认构造函数C++ 默认构造函数C++ 默认构造函数C++ 默认构造函数C++ 默认构造函数C++ 默认构造函数C++ 默认构造函数C++ 默认构造函数C++ 默认构造函数
详解C++的构造函数——构造函数是干什么的、 构造函数的种类和思考测验
C++简单类的实现,包括构造函数,析构函数以及拷贝构造函数