当前位置: 首页 > article >正文

JVM常用概念之新对象实例化

前言

对于大部分的语言,新对象的实例化基本分为三个阶段:分配、系统初始化、用户初始化。

分配

在分配阶段主要需要确定进程空间中是堆区、还是栈区来获取实例数据。

系统初始化

系统初始化指的是特定编程语言的初始化,在C编程语言中,new分配的对象不需要进行初始化,而在Java编程语言中,所有的对象都需要进行系统初始化,具体包含将JVM分配到的内存空间初始化为零值,设置对象头(包含对象的哈希码、GC分代年龄、对象的类元数据信息等)等。

用户初始化

主要指运行与当前对象有关联的任何实例初始化程序和构造函数。

示例

源码

public class Case{
        public Object newInstance(){
                return new Object();
        }
}

编译

public class Case {
     <ClassVersion=55>
     <SourceFile=Case.java>

     public Case() { // <init> //()V
         L0 {
             aload 0 // reference to self
             invokespecial java/lang/Object.<init>()V
             return
         }
     }

     public java.lang.Object newInstance() { //()Ljava/lang/Object;
         L0 {
             new java/lang/Object
             dup
             invokespecial java/lang/Object.<init>()V
             areturn
         }
     }
}

实验

源码

package org.sample;

import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;

@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(value = 3)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
public class UserInit {

    @Benchmark
    public Object init() {
        return new Init(42);
    }

    @Benchmark
    public Object initLeaky() {
        return new InitLeaky(42);
    }

    static class Init {
        private int x;
        public Init(int x) {
            this.x = x;
        }
    }

    static class InitLeaky {
        private int x;
        public InitLeaky(int x) {
            doSomething();
            this.x = x;
        }

        @CompilerControl(CompilerControl.Mode.DONT_INLINE)
        void doSomething() {
            // intentionally left blank
        }
    }
}

编译

public class org/sample/UserInit {
     <ClassVersion=50>
     <SourceFile=UserInit.java>

     public UserInit() { // <init> //()V
         <localVar:index=0 , name=this , desc=Lorg/sample/UserInit;, sig=null, start=L0, end=L1>

         L0 {
             aload 0 // reference to self
             invokespecial java/lang/Object.<init>()V
             return
         }
         L1 {
         }
     }

     public java.lang.Object init() { //()Ljava/lang/Object;
         <localVar:index=0 , name=this , desc=Lorg/sample/UserInit;, sig=null, start=L0, end=L1>

         <visAnno:desc = Lorg/openjdk/jmh/annotations/Benchmark; , values = []>

         L0 {
             new org/sample/UserInit$Init
             dup
             bipush 42
             invokespecial org/sample/UserInit$Init.<init>(I)V
             areturn
         }
         L1 {
         }
     }

     public java.lang.Object initLeaky() { //()Ljava/lang/Object;
         <localVar:index=0 , name=this , desc=Lorg/sample/UserInit;, sig=null, start=L0, end=L1>

         <visAnno:desc = Lorg/openjdk/jmh/annotations/Benchmark; , values = []>

         L0 {
             new org/sample/UserInit$InitLeaky
             dup
             bipush 42
             invokespecial org/sample/UserInit$InitLeaky.<init>(I)V
             areturn
         }
         L1 {
         }
     }
// The following inner classes couldn't be decompiled: org/sample/UserInit$InitLeaky org/sample/UserInit$Init 
}

Init()部分汇编

                                                  ; ------- allocation ----------
0x00007efdc466d4cc: mov    0x60(%r15),%rax          ; TLAB allocation below
0x00007efdc466d4d0: mov    %rax,%r10
0x00007efdc466d4d3: add    $0x10,%r10
0x00007efdc466d4d7: cmp    0x70(%r15),%r10
0x00007efdc466d4db: jae    0x00007efdc466d50a
0x00007efdc466d4dd: mov    %r10,0x60(%r15)
0x00007efdc466d4e1: prefetchnta 0xc0(%r10)
                                                  ; ------- /allocation ---------
                                                  ; ------- system init ---------
0x00007efdc466d4e9: movq   $0x1,(%rax)              ; put mark word header
0x00007efdc466d4f0: movl   $0xf8021bc4,0x8(%rax)    ; put class word header
                                                  ; ...... system/user init .....
0x00007efdc466d4f7: movl   $0x2a,0xc(%rax)          ; x = 42.
                                                  ; -------- /user init ---------

在Init()方法中,没有严格的区分系统初始化和用户初始化的顺序。

InitLeaky()部分汇编

                                                  ; ------- allocation ----------
0x00007fc69571bf4c: mov    0x60(%r15),%rax
0x00007fc69571bf50: mov    %rax,%r10
0x00007fc69571bf53: add    $0x10,%r10
0x00007fc69571bf57: cmp    0x70(%r15),%r10
0x00007fc69571bf5b: jae    0x00007fc69571bf9e
0x00007fc69571bf5d: mov    %r10,0x60(%r15)
0x00007fc69571bf61: prefetchnta 0xc0(%r10)
                                                  ; ------- /allocation ---------
                                                  ; ------- system init ---------
0x00007fc69571bf69: movq   $0x1,(%rax)              ; put mark word header
0x00007fc69571bf70: movl   $0xf8021bc4,0x8(%rax)    ; put class word header
0x00007fc69571bf77: mov    %r12d,0xc(%rax)          ; x = 0 (%r12 happens to hold 0)
                                                  ; ------- /system init --------
                                                  ; -------- user init ----------
0x00007fc69571bf7b: mov    %rax,%rbp
0x00007fc69571bf7e: mov    %rbp,%rsi
0x00007fc69571bf81: xchg   %ax,%ax
0x00007fc69571bf83: callq  0x00007fc68e269be0       ; call doSomething()
0x00007fc69571bf88: movl   $0x2a,0xc(%rbp)          ; x = 42
                                                  ; ------ /user init ------

在InitLeaky()方法中,由于优化器无法确定是否需要x的值,它们必须假设最坏的情况,首先执行系统初始化,然后再完成用户初始化。


http://www.kler.cn/a/573415.html

相关文章:

  • Ubuntu录屏--OBS
  • 什么是组态软件
  • 【DOM 型 XSS举例】
  • 分库分表 MyBatis的拦截器(Interceptor)在 SQL 执行前动态修改表名
  • 前端埋点项目从设计到实现详解
  • 小程序分类页面
  • Tomcat 是什么?有什么功能和作用?为什么启动 Spring 或 Spring Boot 项目需要 Tomcat?
  • 基于编程语言的建筑行业施工图设计系统开发可行性研究————从参数化建模到全流程自动化的技术路径分析
  • 跳跃游戏||力扣--45
  • 【零基础到精通Java合集】第二十九集:SQL常用优化手段
  • 雷军曝光小米影像外挂,大镜头吸附,手机变单反
  • 山东大学计算机科学与技术学院软件工程实验日志
  • Spring IoC配置(xml+FactoryBean)
  • doris: PostgreSQL
  • 极狐GitLab 17.9 正式发布,40+ DevSecOps 重点功能解读【三】
  • gmock和cppfreemock原理学习
  • 统计建模小贴士
  • CC++链接数据库(MySQL)超级详细指南
  • Rust编程实战:Rust实现简单的Web服务,单线程性能问题
  • CHAPTER 6 Object References, Mutability, and Recycling