jvm
骁兵
这个作者很懒,什么都没留下…
展开
-
普通对象(不包括数组对象、Class对象)的创建
加载类:当执行new语句时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过,如果没有,那必须先执行相应类的加载过程。分配内存(每个对象占用的内存都是连续的):对象所需内存大小在类加载完成后便可完全确定。根据Java堆中的内存是否规整(用过的内存都放在一边,空闲的内存放在另一边),分两种分配方式: 指针碰撞(Bump th原创 2017-05-06 12:18:34 · 854 阅读 · 0 评论 -
虚拟机内存结构概述
每一个线程都有一个程序计数器(Program Counter Register),如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是native方法,这个计数器的值则为空 虚拟机栈(Java Virtual Machine Stack)也是线程私有的,它描述了java方法执行的内存模型:每个方法在执行时会创建一个栈帧(Stack Frame)原创 2017-05-06 12:14:34 · 1785 阅读 · 0 评论 -
JDK工具
JDK命令行工具jps:虚拟机进程状况工具 用于列出正在运行的虚拟机进程,并显示虚拟机执行主类(main函数所在类)名称以及这些进程的本地虚拟机唯一ID(Local Virtual Machine Identifier,LVMID),对于本地虚拟机进程来说,LVMID与操作系统的进程ID是一致的。 格式:jps [ options ] [ hostid ]jstat:虚拟机统计信息 用于显原创 2017-05-10 11:12:27 · 265 阅读 · 0 评论 -
确定可回收内存
垃圾回收关注的是堆和方法区两个区域。可达性分析算法以“GC Roots”对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连,则此对象是不可用的。 可做为GC Roots的对象包括以下几种:虚拟机栈(栈帧中的本地变量表)中引用的对象本地方法栈中JNI(native方法)引用的对象方法区中类静态属性引用的对象方法区中常量引用的对象原创 2017-05-06 12:36:16 · 265 阅读 · 0 评论 -
调用方法
方法调用 方法调用是指确定被调用方法的版本(即调用哪一个方法),而不是具体方法里面代码的执行。 Java程序编译后生成的是Class文件,Class文件的编译过程并不包含传统编译中的连接步骤,一切方法调用在Class文件里面存储的都是符号引用,而不是方法在实际运行时内存布局中的入口地址。这也使得Java的方法调用过程变得相对复杂起来,有些方法在类加载过程的解析阶段被确定,有些甚至要等到实际运原创 2017-05-29 10:50:39 · 1185 阅读 · 0 评论 -
运行时栈帧结构
概述 栈帧用于支持虚拟机进行方法调用和方法执行的数据结构,是虚拟机栈的栈元素,存储了方法的局部变量表、操作数栈、动态链接和方法返回地址等信息。每一个方法从调用开始至执行完成的过程,都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程。 在编译代码的时候,栈帧中需要多大的局部变量表,多深的操作数栈都已经操作数栈都已经完全确定,并且写入到方法表的Code属性之中,因此一个栈帧需要分配多少内存,不会受原创 2017-05-28 21:39:53 · 1139 阅读 · 0 评论 -
类加载器
概述 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类,实现这个动作的代码模块称为“类加载器”。 对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟中的唯一性。说通俗一些,比较两个类是否“相等”,只有在两个类是由同一个类加载器的前提之下才有意义,否则,即原创 2017-05-28 21:28:20 · 210 阅读 · 0 评论 -
类的加载过程
概述 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。它们开始的顺序如下图所示: 解析阶段在某些情况下可以在初始化阶段之后再开始。初始化的发生时间 虚拟机规范没有规定什么情况下进行加载过程,但规定了有且只有5种情况必须立即对类进行“初始化”(而加载、验证、准备自然需要在此之前开始):遇到new、gets原创 2017-05-28 13:16:34 · 395 阅读 · 0 评论 -
字节码指令集
具体参见:字节码指令集简介原创 2017-05-28 12:59:22 · 318 阅读 · 0 评论 -
class文件结构
概述 Java虚拟机实现了语言无关性的关键在它不和包括Java在内的任何语言绑定,它只与“class文件”这种特定的二进制文件格式关联,Class文件中包括了Java虚拟机指令集和符号表以及其他辅助信息,编程语言语言只要实现自身的编译器,将源码编译成class文件,即可以在JVM上运行。时至今日,商业机构和开源机构已经在Java语言之外发展出了一大批在Java虚拟机之上运行的语言,如Clojure原创 2017-05-28 11:27:02 · 243 阅读 · 0 评论 -
属性表集合
属性表(attribute_info)在前面的讲解之中已经出现过数次,在Class文件、字段表、方法表都可以携带自己的属性表集合,以用于描述某些场景专有的信息。 虚拟机规范定义的属性 Code属性 Java程序方法体中的代码经过Javac编译器处理后,最终变为字节码指令存储在Code属性内。Code属性出现在方法表的属性集合之中,但并非所有的方法表都必须存在这个属性,譬如接原创 2017-05-28 12:47:11 · 4664 阅读 · 1 评论 -
class文件常量池
常量池的入口需要放置一项u2类型的数据,代表常量池容量计数值(constant_pool_count) 常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References) 字面量比较接近于Java语言层面的常量概念,如文本字符串、声明为final的常量值等 符号引用则属于编译原理方面的概念,包括了下面三类常量: 1、类和接口的全限定名原创 2017-05-28 12:15:53 · 361 阅读 · 0 评论 -
内存分配与回收策略
优先在Eden区分配 大多数情况下,对象优先在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC。 -XX:PrintGCDetails:打印内存回收日志 -XX:SurvivorRatio=8:Eden区和Survivor区的空间比例是8:1 大对象直接进入老年代 虚拟机提供了一个-XX:PretenureSizeThresh原创 2017-05-06 13:17:52 · 490 阅读 · 0 评论 -
垃圾收集器
收集器概览 上面一个区域是新生代收集器,下面一个区域是老年代收集器。如果两个收集器之间存在连线,就说明它们可以搭配使用。Serial收集器 采用复制算法,单线程,在垃圾收集时必须暂停其他所有的工作线程,直到收集结束。适用于小型client应用,如桌面应用。下图为Serial和Serial Old收集器搭配使用。 ParNew收集器 采用复制算法,是Serial收集器的多线程版本。适用原创 2017-05-06 12:54:07 · 254 阅读 · 0 评论 -
垃圾收集算法
标记-清除算法 缺点:会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配大对象时,无法找到足够的连续内存而不得不提前出发一次垃圾收集动作。复制算法 将内存划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉。 缺点:内存缩小了一半 改进:不按照1:1的比例来划分内存空间,而是原创 2017-05-06 12:44:06 · 211 阅读 · 0 评论 -
安装Eclipse Memory Analyzer
1、在官网下载压缩包:http://www.eclipse.org/mat/ 2、将压缩包解压到Eclipse的dropins目录下 3、重启Eclipse原创 2017-05-06 12:29:03 · 249 阅读 · 0 评论 -
对象的访问定位
1、使用句柄 优点:当对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要修改2、使用直接指针(HotSpot使用这种方式) 优点:速度更快,节省了一次指针定位的时间开销原创 2017-05-06 12:28:48 · 178 阅读 · 0 评论 -
对象内存布局
1、对象头(Header)Mark Word:存储对象自身的运行时数据,如果哈希吗、GC分代年龄、锁状态标识、线程持有的锁、偏向线程ID、偏向时间戳等,这部分数据在32位和64位虚拟机中(未开启压缩指针)分别是32bit和64bit类型指针:执行类元数据的指针,虚拟机通过这个指针确定这个对象是哪个类的实例。数组长度:如果对象是一个Java数组,用于记录数组长度的数据。因为虚拟机可以通过普通Ja原创 2017-05-06 12:26:08 · 249 阅读 · 0 评论 -
String.intern()方法详解
在JDK1.6中,所有共享的 String 对象都存储在 PermGen(方法区) 中,PermGen 的大小是固定的并且在运行时是无法扩展的。你可以使用 -XX:MaxPermSize=N 配置来调整它的大小。到了Java7时代,字符串池的位置被调整到 heap 中了,这意味着你再也不会被固定的内存空间限制了。所有的字符串都保存在堆(heap)中同其他普通对象一样,这使得你在调优应用时仅需要调整堆原创 2017-05-30 22:06:03 · 420 阅读 · 0 评论