java类静态变量初始化在openjdk17源码中体现

##有请志愿者OtherClass.java

public class OtherClass {private static int CONSTANT_O=9876;public int o=1234;public void dddd(){String dddd = "dddd";System.out.println(dddd+CONSTANT_O);}}

类字节码

Classfile /home/yym/debug-java/OtherClass.classLast modified Oct. 28, 2024; size 973 bytesMD5 checksum 807f1e8fc3640c40a826bc5905a9ae6aCompiled from "OtherClass.java"
public class OtherClassminor version: 0major version: 55flags: (0x0021) ACC_PUBLIC, ACC_SUPERthis_class: #8                          // OtherClasssuper_class: #9                         // java/lang/Objectinterfaces: 0, fields: 2, methods: 3, attributes: 3
Constant pool:#1 = Methodref          #9.#21         // java/lang/Object."<init>":()V#2 = Fieldref           #8.#22         // OtherClass.o:I#3 = String             #17            // dddd#4 = Fieldref           #23.#24        // java/lang/System.out:Ljava/io/PrintStream;#5 = Fieldref           #8.#25         // OtherClass.CONSTANT_O:I#6 = InvokeDynamic      #0:#29         // #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;#7 = Methodref          #30.#31        // java/io/PrintStream.println:(Ljava/lang/String;)V#8 = Class              #32            // OtherClass#9 = Class              #33            // java/lang/Object#10 = Utf8               CONSTANT_O#11 = Utf8               I#12 = Utf8               o#13 = Utf8               <init>#14 = Utf8               ()V#15 = Utf8               Code#16 = Utf8               LineNumberTable#17 = Utf8               dddd#18 = Utf8               <clinit>#19 = Utf8               SourceFile#20 = Utf8               OtherClass.java#21 = NameAndType        #13:#14        // "<init>":()V#22 = NameAndType        #12:#11        // o:I#23 = Class              #34            // java/lang/System#24 = NameAndType        #35:#36        // out:Ljava/io/PrintStream;#25 = NameAndType        #10:#11        // CONSTANT_O:I#26 = Utf8               BootstrapMethods#27 = MethodHandle       6:#37          // REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;#28 = String             #38            // \u0001\u0001#29 = NameAndType        #39:#40        // makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;#30 = Class              #41            // java/io/PrintStream#31 = NameAndType        #42:#43        // println:(Ljava/lang/String;)V#32 = Utf8               OtherClass#33 = Utf8               java/lang/Object#34 = Utf8               java/lang/System#35 = Utf8               out#36 = Utf8               Ljava/io/PrintStream;#37 = Methodref          #44.#45        // java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;#38 = Utf8               \u0001\u0001#39 = Utf8               makeConcatWithConstants#40 = Utf8               (Ljava/lang/String;I)Ljava/lang/String;#41 = Utf8               java/io/PrintStream#42 = Utf8               println#43 = Utf8               (Ljava/lang/String;)V#44 = Class              #46            // java/lang/invoke/StringConcatFactory#45 = NameAndType        #39:#50        // makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;#46 = Utf8               java/lang/invoke/StringConcatFactory#47 = Class              #52            // java/lang/invoke/MethodHandles$Lookup#48 = Utf8               Lookup#49 = Utf8               InnerClasses#50 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;#51 = Class              #53            // java/lang/invoke/MethodHandles#52 = Utf8               java/lang/invoke/MethodHandles$Lookup#53 = Utf8               java/lang/invoke/MethodHandles
{public int o;descriptor: Iflags: (0x0001) ACC_PUBLICpublic OtherClass();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack=2, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: aload_05: sipush        12348: putfield      #2                  // Field o:I11: returnLineNumberTable:line 1: 0line 4: 4public void dddd();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack=3, locals=2, args_size=10: ldc           #3                  // String dddd2: astore_13: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;6: aload_17: getstatic     #5                  // Field CONSTANT_O:I10: invokedynamic #6,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;15: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V18: returnLineNumberTable:line 8: 0line 9: 3line 10: 18static {};descriptor: ()Vflags: (0x0008) ACC_STATICCode:stack=1, locals=0, args_size=00: sipush        98763: putstatic     #5                  // Field CONSTANT_O:I6: returnLineNumberTable:line 3: 0
}
SourceFile: "OtherClass.java"
InnerClasses:public static final #48= #47 of #51;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:0: #27 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;Method arguments:#28 \u0001\u0001

 ##类静态变量初始化

// Make sure klass is initialized
  klass->initialize(CHECK);

JRT_ENTRY(void, InterpreterRuntime::_new(JavaThread* current, ConstantPool* pool, int index))Klass* k = pool->klass_at(index, CHECK);InstanceKlass* klass = InstanceKlass::cast(k);// Make sure we are not instantiating an abstract klassklass->check_valid_for_instantiation(true, CHECK);// Make sure klass is initializedklass->initialize(CHECK);// At this point the class may not be fully initialized// because of recursive initialization. If it is fully// initialized & has_finalized is not set, we rewrite// it into its fast version (Note: no locking is needed// here since this is an atomic byte write and can be// done more than once).//// Note: In case of classes with has_finalized we don't//       rewrite since that saves us an extra check in//       the fast version which then would call the//       slow version anyway (and do a call back into//       Java).//       If we have a breakpoint, then we don't rewrite//       because the _breakpoint bytecode would be lost.oop obj = klass->allocate_instance(CHECK);// std::cout << "@@@@yym%%%%obj address " << klass->name()->as_C_string() << obj << "----begin" << std::endl;current->set_vm_result(obj);
JRT_END

##void InstanceKlass::initialize_impl(TRAPS) 方法步骤8初始化静态

// Step 8{DTRACE_CLASSINIT_PROBE_WAIT(clinit, -1, wait);if (class_initializer() != NULL) {// Timer includes any side effects of class initialization (resolution,// etc), but not recursive entry into call_class_initializer().PerfClassTraceTime timer(ClassLoader::perf_class_init_time(),ClassLoader::perf_class_init_selftime(),ClassLoader::perf_classes_inited(),jt->get_thread_stat()->perf_recursion_counts_addr(),jt->get_thread_stat()->perf_timers_addr(),PerfClassTraceTime::CLASS_CLINIT);call_class_initializer(THREAD);} else {// The elapsed time is so small it's not worth counting.if (UsePerfData) {ClassLoader::perf_classes_inited()->inc();}call_class_initializer(THREAD);}}

##JavaCalls::call执行clinit 字节码,初始化静态变量

##clinit 方法
Method* InstanceKlass::class_initializer() const {Method* clinit = find_method(vmSymbols::class_initializer_name(), vmSymbols::void_method_signature());if (clinit != NULL && clinit->has_valid_initializer_flags()) {return clinit;}return NULL;
}
##JavaCalls::call执行clinit 字节码
void InstanceKlass::call_class_initializer(TRAPS) {if (ReplayCompiles &&(ReplaySuppressInitializers == 1 ||(ReplaySuppressInitializers >= 2 && class_loader() != NULL))) {// Hide the existence of the initializer for the purpose of replaying the compilereturn;}methodHandle h_method(THREAD, class_initializer());assert(!is_initialized(), "we cannot initialize twice");LogTarget(Info, class, init) lt;if (lt.is_enabled()) {ResourceMark rm(THREAD);LogStream ls(lt);ls.print("%d Initializing ", call_class_initializer_counter++);name()->print_value_on(&ls);ls.print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", p2i(this));}if (h_method() != NULL) {JavaCallArguments args; // No argumentsJavaValue result(T_VOID);JavaCalls::call(&result, h_method, &args, CHECK); // Static call (no args)}
}

##执行putstatic字节码

// Fields
//void InterpreterRuntime::resolve_get_put(JavaThread* current, Bytecodes::Code bytecode) {// resolve fieldfieldDescriptor info;LastFrameAccessor last_frame(current);constantPoolHandle pool(current, last_frame.method()->constants());methodHandle m(current, last_frame.method());bool is_put    = (bytecode == Bytecodes::_putfield  || bytecode == Bytecodes::_nofast_putfield ||bytecode == Bytecodes::_putstatic);bool is_static = (bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic);{JvmtiHideSingleStepping jhss(current);JavaThread* THREAD = current; // For exception macros.LinkResolver::resolve_field_access(info, pool, last_frame.get_index_u2_cpcache(bytecode),m, bytecode, CHECK);} // end JvmtiHideSingleStepping// check if link resolution caused cpCache to be updatedConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry();if (cp_cache_entry->is_resolved(bytecode)) return;// compute auxiliary field attributesTosState state  = as_TosState(info.field_type());// Resolution of put instructions on final fields is delayed. That is required so that// exceptions are thrown at the correct place (when the instruction is actually invoked).// If we do not resolve an instruction in the current pass, leaving the put_code// set to zero will cause the next put instruction to the same field to reresolve.// Resolution of put instructions to final instance fields with invalid updates (i.e.,// to final instance fields with updates originating from a method different than <init>)// is inhibited. A putfield instruction targeting an instance final field must throw// an IllegalAccessError if the instruction is not in an instance// initializer method <init>. If resolution were not inhibited, a putfield// in an initializer method could be resolved in the initializer. Subsequent// putfield instructions to the same field would then use cached information.// As a result, those instructions would not pass through the VM. That is,// checks in resolve_field_access() would not be executed for those instructions// and the required IllegalAccessError would not be thrown.//// Also, we need to delay resolving getstatic and putstatic instructions until the// class is initialized.  This is required so that access to the static// field will call the initialization function every time until the class// is completely initialized ala. in 2.17.5 in JVM Specification.InstanceKlass* klass = info.field_holder();bool uninitialized_static = is_static && !klass->is_initialized();bool has_initialized_final_update = info.field_holder()->major_version() >= 53 &&info.has_initialized_final_update();assert(!(has_initialized_final_update && !info.access_flags().is_final()), "Fields with initialized final updates must be final");Bytecodes::Code get_code = (Bytecodes::Code)0;Bytecodes::Code put_code = (Bytecodes::Code)0;if (!uninitialized_static) {get_code = ((is_static) ? Bytecodes::_getstatic : Bytecodes::_getfield);if ((is_put && !has_initialized_final_update) || !info.access_flags().is_final()) {put_code = ((is_static) ? Bytecodes::_putstatic : Bytecodes::_putfield);}}// std::cout << "@@@@yym%%%%field" << info.name()->as_C_string() << ":offset:" << info.offset() << std::endl;cp_cache_entry->set_field(get_code,put_code,info.field_holder(),info.index(),info.offset(),state,info.access_flags().is_final(),info.access_flags().is_volatile());
}

##设置字段  cp_cache_entry->set_field

void ConstantPoolCacheEntry::set_field(Bytecodes::Code get_code,Bytecodes::Code put_code,Klass* field_holder,int field_index,int field_offset,TosState field_type,bool is_final,bool is_volatile) {set_f1(field_holder);set_f2(field_offset);assert((field_index & field_index_mask) == field_index,"field index does not fit in low flag bits");set_field_flags(field_type,((is_volatile ? 1 : 0) << is_volatile_shift) |((is_final    ? 1 : 0) << is_final_shift),field_index);set_bytecode_1(get_code);set_bytecode_2(put_code);NOT_PRODUCT(verify(tty));
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/58317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django入门教程——动态表格分页展示数据

第五章 动态表格分页展示数据 教学目的 初步了解layui的使用理解table组件在layui中的应用了解数据添加、删除、编辑操作引入JavaScript框架的优势 layUI动态表格 表格组件 table 是 Layui 中使用率极高的一个组件&#xff0c;它以表格的承载方式对数据进行渲染、重载、排序…

Python数据分析NumPy和pandas(十五、pandas 数据加载、存储和文件格式)

大多数时候&#xff0c;我们要处理分析的数据是存储在不同格式的文件中的&#xff0c;有txt、csv、excel、json、xml以及二进制等磁盘文件格式&#xff0c;还有时候是从数据库以及从Web API中交互获取要处理的数据。现在开始学习如何用pandas从以上内容中输入和输出数据。 读取…

CRC校验 生成多项式选取奇次偶次的问题讨论

目录 问题一&#xff1a;为什么CRC校验码不支持偶次校验码&#xff1f; 问题二&#xff1a;如何判断一个生成多项式是否为偶次多项式&#xff1f; 步骤&#xff1a; 示例&#xff1a; 注意&#xff1a; 问题三&#xff1a;CRC32的生成多项式是什么&#xff1f;是偶次还是…

【小程序上传图片封装2024,支持多图,带进度,上传头像】

import config from ./config;// 支持多图&#xff0c;显示进度 export function uploadImages(count 1, sourceType, onLoading null, showProgress false, fileKey file) {return new Promise((resolve, reject) > {wx.chooseMedia({count: count, // 可以选择的图片数…

Mac上面压缩文件出现__MACOSX文件夹问题

问题 最近需要上传前端zip包&#xff0c;但是&#xff0c;mac右键压缩dist目录的时候&#xff0c;能正常压缩。但是解压这个目录的时候出现了__MACOSX文件夹&#xff0c;是真的坑。 解决 zip -r -X <文件名>.zip <需要压缩的目录>例子如下&#xff1a; zip -r …

Chromium HTML5 新的 Input 类型date 对应c++

一、Input 类型: date date 类型允许你从一个日期选择器选择一个日期。 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>test</title> </head> <body><form action"demo-form.php"…

Docker 常用命令全解析:提升对雷池社区版的使用经验

Docker 常用命令解析 Docker 是一个开源的容器化平台&#xff0c;允许开发者将应用及其依赖打包到一个可移植的容器中。以下是一些常用的 Docker 命令及其解析&#xff0c;帮助您更好地使用 Docker。 1. Docker 基础命令 查看 Docker 版本 docker --version查看 Docker 运行…

python 爬虫 入门 五、抓取图片、视频

目录 一、图片、音频 二、下载视频&#xff1a; 一、图片、音频 抓取图片的手法在上一篇python 爬虫 入门 四、线程&#xff0c;进程&#xff0c;协程-CSDN博客里面其实有&#xff0c;就是文章中的图片部分&#xff0c;在那一篇文章&#xff0c;初始代码的28&#xff0c;29行…

保姆级教程 | 全流程免费:合并多份长宽不同的PDF成相同大小并进行瘦身

背景 由于老板需要&#xff0c;完成不同PDF文件&#xff08;a&#xff0c;b&#xff0c;c....&#xff09;合并&#xff0c;同时要求主文件&#xff08;A&#xff09;小于6M。合并过程中发现各个PDF大小&#xff08;长宽&#xff09;并不相同&#xff0c;造成合并后效果不好也…

如何将 HashiCorp Vault 与 Node.js 集成:安全管理敏感数据

在处理密码、API 密钥或个人用户信息等敏感数据时,安全存储它们至关重要。在源代码中硬编码机密或将其保存在纯文本文件中是一种危险的方法。这就是 HashiCorp Vault 发挥作用的地方。 Vault 是一个用于管理机密(例如凭证、API 密钥和敏感配置)的开源工具。 在本教程中,我将…

Vue3 学习笔记(八)Vue3 语法-Class 与 Style绑定详解

在 Vue.js 中&#xff0c;动态地绑定 CSS 类和样式是一项常见的需求。Vue 提供了几种不同的方法来实现这一点&#xff0c;包括对象语法、数组语法和组件的作用域插槽。 以下是这些方法的详细说明&#xff1a; 一、Class 绑定 1、对象语法 对象语法允许根据表达式的真值动态地切…

java知识管理系统源码(springboot)

项目简介 知识管理系统实现了以下功能&#xff1a; 知识管理系统的主要使用者分为管理员和用户两个角色。管理员功能有个人中心&#xff0c;用户管理&#xff0c;文章分类管理&#xff0c;文章信息管理&#xff0c;资料分类管理&#xff0c;资料下载管理&#xff0c;问答管理…

信捷 PLC C语言 定时器在FC中的使用

传统梯形图的定时器程序写起来简单&#xff0c;本文用C语言写定时器的使用。 定时器在c语言中使用&#xff0c;和普通梯形图中使用的区别之一是既有外部条件&#xff0c;也有内部条件。 1.建全局变量 2.建立FC POU 这个是功能POU程序。 这里的Enable是内部条件 3.调用包含定…

从JDK 17 到 JDK 21:Java 新特性

JDK17 密封类 概念&#xff1a;密封类允许开发者控制哪些类可以继承或实现特定的类或接口。通过这种方式&#xff0c;密封类为类的继承提供了更高的安全性和可维护性。 定义&#xff1a;使用sealed代表该类为密封类&#xff0c;并用permits限制哪些类可以继承。 public sea…

重写(外壳不变)

重写&#xff1a;是子类对父类非静态、非private修饰、非final修饰、非构造方法等的实现过程进行重新编写返回值和形参都不能改变。 重写的好处&#xff1a;子类可以根据需要&#xff0c;定义专属于自己的行为。&#xff08;子类能够根据需要实现父类的方法&#xff09; 方法…

大数据日志处理框架ELK方案

介绍应用场景大数据ELK日志框架安装部署 一&#xff0c;介绍 大数据日志处理框架ELK&#xff08;Elasticsearch、Logstash、Kibana&#xff09;是一套完整的日志集中处理方案&#xff0c;以下是对其的详细介绍&#xff1a; 一、Elasticsearch&#xff08;ES&#xff09; 基本…

Golang | Leetcode Golang题解之第515题在每个树行中找最大值

题目&#xff1a; 题解&#xff1a; func largestValues(root *TreeNode) (ans []int) {if root nil {return}q : []*TreeNode{root}for len(q) > 0 {maxVal : math.MinInt32tmp : qq nilfor _, node : range tmp {maxVal max(maxVal, node.Val)if node.Left ! nil {q …

怎么理解ES6 Proxy

Proxy 可以理解成&#xff0c;在目标对象之前架设一层 “拦截”&#xff0c;外界对该对象的访问&#xff0c;都必须先通过这层拦截&#xff0c;因此提供了一种机制&#xff0c;可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理&#xff0c;用在这里表示由它来 “代理…

前端知识串联笔记(更新中...)

1.MVVM MVVM 是指 Model - View - ViewModel&#xff0c;Model 是数据与业务逻辑&#xff0c;View 是视图&#xff0c;ViewModel 用于连接 View 和 Model Model ---> View&#xff1a;将数据转化成所看到的页面&#xff0c;实现的方式&#xff1a;Data Bindings -- 数据绑定…

.NET Core WebApi第6讲:WebApi的前端怎么派人去拿数据?(区别MVC)

一、前端界面小基础 head&#xff1a;引入CSS, 引入JS是写在head里面。 body&#xff1a;眼睛肉眼能看到的用户展示的界面是写在body里面。 二、前端怎么派人去拿数据&#xff1f; 1、MVC&#xff1a;前后端不分离&#xff0c;MVC相比WebApi只是多了一个views的文件夹 &am…