字节码

三、JVM之方法区

空扰寡人 提交于 2020-01-18 18:48:04
一、什么式方法区 方法区,也称非堆(Non-Heap),又是一个被线程共享的内存区域。其中主要存储加载的类字节码、class/method/field等元数据对象、static-final常量、static变量、jit编译器编译后的代码等数据。另外,方法区包含了一个特殊的区域“运行时常量池”。 (1)加载的类字节码:要使用一个类,首先需要将其字节码加载到JVM的内存中。至于类的字节码来源,可以多种多样,如.class文件、网络传输、或cglib字节码框架直接生成。 (2)class/method/field等元数据对象:字节码加载之后,JVM会根据其中的内容,为这个类生成Class/Method/Field等对象,它们用于描述一个类,通常在反射中用的比较多。不同于存储在堆中的java实例对象,这两种对象存储在方法区中。 (3)static-final常量、static变量:对于这两种类型的类成员,JVM会在方法区为它们创建一份数据,因此同一个类的static修饰的类成员只有一份; (4)jit编译器的编译结果:以hotspot虚拟机为例,其在运行时会使用JIT即时编译器对热点代码进行优化,优化方式为将字节码编译成机器码。通常情况下,JVM使用“解释执行”的方式执行字节码,即JVM在读取到一个字节码指令时,会将其按照预先定好的规则执行栈操作,而栈操作会进一步映射为底层的机器操作

运行期优化

一曲冷凌霜 提交于 2020-01-18 12:41:00
分层编译 JVM在执行的时候会把字节码转化为机械码 JVM将执行状态分成了5个层次 第0层:解释执行(Interpreter),只是单纯的把字节码转化为机械码 第1层:使用C1即时编译器编译执行(不带profiling) 即时编译器(JIT)将一些字节码转化为机械码,并存入Code Cache,下次遇到相同的代码就可以直接执行,不用像解释器一样重复解释 profiling:在运行过程中收集一些程序执行状态的睡觉,例如方法的调用次数,循环的次数等 第2层:使用C1即时编译器编译执行(带基本profiling) 第3层:使用C1即时编译器编译执行(带完全的profiling) 第4层:使用C2即时编译器编译执行 注意 解释器把字节码解释为所有平台都通用的机器码 即时编译器生成平台特定的机械码 逃逸分析(在c2) 在下列代码,创建的对象根本及没有在for循环外被调用,那么,c2编译器干脆就改变你的字节码,就不创建他 方法内联 把方法内的代码方法调用者的位置,还可以进行常量折叠 来源: CSDN 作者: 今天又学java了 链接: https://blog.csdn.net/weixin_43907800/article/details/104027297

【Java】介绍与术语解释

…衆ロ難τιáo~ 提交于 2020-01-18 12:22:57
Java版本 Java SE :标准开发。 Java EE :企业平台搭建,互联网开发。 Java ME:为移动设备和嵌入式设备提供健壮且灵活的环境,基本上被Android替代了。 Java主要特征 纯面向对象的编程语言。 提供方便的 内存回收 处理机制。(由于牵扯到自动化,就要考虑优化的问题) 避免的复杂的指针问题,而使用 引用来代替指针 。 支持 多线程编程 的语言,处理的性能得到提升。 提供高效的 网络处理 能力,可以基于NIO实现更加高效的传输处理。 具有良好的 可移植性 :同一个程序可以在不同的操作系统上部署,依靠JVM(Java虚拟机) Java程序运行机制 Java是编译型与解释型的结合: .java文件(源文件)---编译--->.class文件(字节码文件)---解释--->机器码指令 所有Java程序的解释都要求放在Java虚拟机上处理。 Java虚拟机 虚拟机:指在一台计算机上由软件或硬件模拟的计算机。它具有自己完善的硬件架构,如处理器、堆栈(Stack)、寄存器等,还具有相应的指令系统(字节码就是一种指令格式)。 Java编译器: 将Java源文件(.java文件)编译成字节码文件(.class文件,特殊的二进制文件)javac.exe可以简单看成是Java编译器。 Java解释器: 是JVM的一部分。Java解释器用来 解释执行 (先解释再执行

JavaScript的工作原理

北城余情 提交于 2020-01-18 02:45:04
  在学习Web前端的时候,有很多重要的知识点需要我们深刻理解并掌握实际运用场景。例如,JavaScript是Web前端人员必须要掌握的知识点之一,下面,为大家全面介绍JavaScript的工作原理,希望对大家高效学习Web前端有所帮助。   JavaScript引擎是什么?   JavaScript引擎是一种用于将我们的代码转换为机器可读语言的引擎。如果没有JavaScript引擎,你编写的代码对计算机来说简直是一堆“胡言乱语”。不仅仅是JavaScript,其他所有编程语言都需要一个类似的引擎,来将这些“胡言乱语”转换成对计算机有意义的语言。   JavaScript引擎的组成部分有哪些?   1、编译器。主要工作是将源代码编译成抽象语法树,然后在某些引擎中还包含将抽象语法树转换成字节码。   2、解释器。在某些引擎中,解释器主要是接受字节码,解释执行这个字节码,然后也依赖来及回收机制等。   3、JIT工具。一个能够JIT的工具,将字节码或者抽象语法树转换成本地代码,当然它也需要依赖牢记垃圾回收器和分析工具(profiler)。它们负责垃圾回收和收集引擎中的信息,帮助改善引擎的性能和功效。   JavaScript引擎是如何工作的?   JavaScript的工作形式取决于是什么引擎。目前比较常用的JavaScript引擎有两个

JVM 调优实战--JVM字节码

拜拜、爱过 提交于 2020-01-17 15:39:32
目录 通过javap命令查看class文件的字节码内容 常量池 ​描述符 字段描述符 方法描述符 解读方法字节码 图解 研究i++与++i的不同 查看字节码 对比 分析字符串拼接孰优孰劣 小结 通过javap命令查看class文件的字节码内容 通过javap命令查看字节码并将内容写入到Test1.txt文件中的命令: javap -v Test1.class > Test.txt 打开Test1.txt文件: 常量池 描述符 字段描述符 方法描述符 解读方法字节码 图解 研究i++与++i的不同 查看字节码 对比 分析字符串拼接孰优孰劣 编写测试案例: m1方法的执行过程中,jvm底层会new StringBuilder()进行处理; 结论:m1方法中虽然在代码中使用的是+号拼接,但是在字节码中也被编译成了StringBuilder的方式。因此可以得出结论: 字符串拼接,+号和StringBuilder是相等的,效率一样。 再来看一个案例: m1方法,底层JVM的执行过程是循环多少次就new多少个StringBuilder对象: goto语句,比如goto 5,跳转到第5行继续执行。 m2方法,JVM的层只new了一个StringBuilder对象: 结论:m1的效率明显低于m2方法。 小结 使用字节码的方式可以很好地查看代码底层的执行,从而可以看出哪些实现效率高,哪些实现效率低

类文件结构

六月ゝ 毕业季﹏ 提交于 2020-01-17 13:36:28
Class文件格式只有两种数据类型:无符号数和表。 ① 无符号数属于基本的数据类型,以u1,u2,u4,u8来分别代表1个字节,2个字节,4个字节和8个字节的无符号数;可用来描述数字,索引引用,数量值或者按照UTF-8编码构成的字符串值。 ② 表是由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地以“_info”结尾。表用于描述由层次关系的复合结构的数据,整个Class文件本质上就是一张表。 魔数:每个class文件的头4个字节(0-3字节)(16进制),用来确定文件是否为一个可以被虚拟机接受的class文件,不用文件扩展名作为标识是因为扩展名可以随意改动 第4,5字节是次版本号;6,7字节是主版本号(JDK向下兼容以前版本的class文件)(0034是java 8) 8-9字节表示常量池的长度,0023表示常量池有#1~#34项(#0项不计入,也没有值) 常量池是在*.class文件中的一张表,常量池中存放两大常量项: ① 字面量(文本字符串,声明为final的常量值); ② 符号引用(类和接口的全限定名 (Fully Qualified Name)、字段的名称和描述符、方法的名称和描述符); 虚拟机根据这张表找到要执行的类名,方法名,参数类型,字面量等信息, 当类被加载,常量池信息会被放入运行时常量池,并且把里面的符号地址变为真实地址

从字节码看try catch finally的return如何执行

时间秒杀一切 提交于 2020-01-16 20:57:44
文章是对两位博主的总结,提炼,原文如下链接: 从字节码看try catch finally的return如何执行 Java中try catch finally语句中含有return语句的执行情况(总结版) 测试代码很简单,如下: Test.java public class Test { public int get ( ) { try { return 0 ; } catch ( Exception e ) { e . printStackTrace ( ) ; return 1 ; } finally { return 2 ; } } } 执行$ javap -verbose Test.class $ javap - verbose Test . class Classfile / E : / workspace / java / Test . class Last modified 2018 - 1 - 29 ; size 405 bytes MD5 checksum f8f6002de3931b2e95125679f2ce1f6c Compiled from "Test.java" public class Test minor version : 0 major version : 52 flags : ACC_PUBLIC , ACC_SUPER Constant

JVM

北城余情 提交于 2020-01-16 20:04:22
JVM 主要流程图 Java源码编译由以下三个过程组成: 分析和输入到符号表 注解处理 语义分析和生成class文件 编译时期-语法糖 语法糖可以看做是编译器实现的一些“小把戏”,这些“小把戏”可能使得效率大大提升 其中最值得说的就是泛型了,这个语法糖可以说被我们经常使用的 泛型只会在Java源码中存在,编译过后会被替换为原来的原生类型(Row Type,也称为裸类型)。这个过程叫做:泛型擦除 有了泛型这个语法糖后 代码更加简洁【不用强制类型转换】 程序更加强壮【只要编译时期没有警告,那么运行时期就不会出现ClassCastException】 可读性和稳定性【在编写集合的时候,就限定了类型】 JVM实现跨平台 至此,我们通过javac.exe编译器来编译我们的.java文件生成出.class文件 这些.class文件很明显是不能直接运行的,它不像C语音(编译cpp后生成exe文件直接运行) 这些.class文件是交由JVM来解析运行的 JVM是运行在操作系统之上的,每个操作系统的指令是不同,而JDK是区分操作系统的,只要你的本地系统装了JDK,这个JDK就是能够和当前系统兼容的。(jdk是区分平台的,class文件会被翻译成不同的平台的机器编码) class字节码运行在JVM之上,所以不用关系class字节码是在哪个操作系统编译的,只要符合JVM规范,那么

Java内存区域-堆,程序计数器

倖福魔咒の 提交于 2020-01-16 19:58:36
Jvm运行时数据区域-堆,程序计数器 Java堆 堆:Java堆是内存中最大的的一块。Java堆是所有线程共享的的一块内存区域,此内存唯一的目的存放对象实例。几乎所有对象的实例都在这里分配内存。这一点在Java虚拟机规范中描述:所有的对象实例以及数据都要在堆上分配,但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配,标量替换优化技术将会导致一下微妙的变化发生,所有的对象都分配在堆上也渐渐的变得不是那么绝对了。 Java堆是垃圾收集器管理的主要区域(GC堆),现在采用分代收集算法,Java堆分为新生代,和老年代;再细致一点有Eden空间,From Survivor空间,To Survivor空间等。从内存分配的角度来看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)。无论如何划分,都与存放的内容无关,无论哪个区域,存放任然都是对象实例,进一步划分的目的是为了更好的回收内存,或者更快的分配内存。 根据Java虚拟机规定,Java堆可以物理不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现是,既可以实现固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展实现的(t通过-Xmx和-Xms控制(有遇到过))。如果在堆中没有内存完成实例分配,并且无法在扩展时

自动内存管理机制

谁说我不能喝 提交于 2020-01-16 06:03:10
对于Java程序员来说,在虚拟机自动内存管理机制的帮助下,不需要在为每个new操作去写配对的delete/free代码,不容易出现内存泄漏和内存溢出的问题,Java程序员把内存控制的权力交给了Java虚拟机 运行时数据区域 Java虚拟机在执行java程序的过程中会把他所管理的内存划分为若干个不同的数据区域 程序计数器 (program counter register) 概念: 当前线程所执行的字节码的行号解释器 在虚拟机的概念模型里,字节码解释器工作时通过改变计数器的值选取下一条要执行的字节码指令 在物理上,通过寄存器来实现(读取快) 特点: ① 线程私有,每个线程有一个互不影响,用于线程切换后恢复到正确的执行位置 ② 不存在内存溢出 虚拟机栈 (Java Virtual Machine Stacks) 概念: 栈:栈是线程运行时所需要的内存空间 栈帧:栈里面有一个一个的栈帧,栈帧是每个方法运行时所需的内存,所有的方法再执行时创建一个栈帧,用于存储 ① 局部变量表,② 操作数栈(对应当前的指令,栈帧对应的是方法),③ 动态链接, 方法出口等信息 每调用执行一个方法就会往栈里面压入相应的栈帧,执行完再弹出 局部变量表:存放着编译期间可知的各个基本数据类型,对象引用和returnAddress类型(指向一条字节码指令的地址) 对应着当前正在执行的方法的栈帧叫做活动栈帧 特点: ①