Java对象何时创建?从GC视角及构造器异常场景解析
从GC视角看Java对象的创建时机
我真不敢相信居然没人问过这个问题,它听起来非常基础,但我在Stack Overflow上搜索后没找到相关问题(不是那个讨论构造器调用顺序的问题)。
核心问题:从GC的视角来看,Java中的对象何时被创建?
起初我没多想,认为“至少不会早于构造器执行完毕”。后来我发现Mockito使用一些底层原生技术完全绕过构造器。
之后我了解到finalizer相关的安全问题,验证并确认了以下代码:
public class FinalizerAttackExample { public static void main(String[] args) throws InterruptedException { try { new MaliciousSubclass(); } catch(SecurityException ex) { System.out.println("wouldn't get hands on a ResourceClass instance"); } System.gc(); Thread.sleep(2000); } static class ResourceClass { ResourceClass() { if(!checkCaller()) throw new SecurityException(); } public void criticalAction() { System.out.println("ResourceClass.criticalAction()"); } } /** For our demonstration, all callers are invalid */ static boolean checkCaller() { return false; } static class MaliciousSubclass extends ResourceClass { @Override protected void finalize() { System.out.println("see, I got hands on " + this); criticalAction(); } } }
确实会产生如下输出(哈希值可能不同):
wouldn't get hands on a ResourceClass instance see, I got hands on FinalizerAttackExample$MaliciousSubclass@7ad74083 ResourceClass.criticalAction()
这就引出了问题:如果构造器从未成功执行,那么finalize()是在哪个对象上调用的?Java对象是在构造器的虚拟“finally”块中创建的吗?还是在此之前?
以下是Java语言规范中的描述:
A new class instance is explicitly created when evaluation of a class instance creation expression (§15.9) causes a class to be instantiated.
——JLS, §12.5
这个描述完全没有解决我的疑问。
如果这是JVM相关的(本不应如此),假设我们在Hotspot上运行代码。
内容的提问来源于Stack Exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

