第一章 走近java
1.JDK(支持java程序开发的最小环境):java程序设计语言,java虚拟机,java API类库
JRE(支持java程序运行的标准环境):java SE API子集,java虚拟机
2.java平台:Java Card支持java小程序(Applet);Java ME支持java程序在移动端;Java SE面向桌面;Java EE企业级应用
3.JDK1.5:自动装箱、泛型、动态注解、枚举、可变长参数、遍历循环(foreach)
JDK1.6:动态语言支持、编译API、微型HTTP服务器API、锁与同步、垃圾收集、类加载
JDK1.7:新的G1收集器、加强对非java语言的调用支持、升级类加载架构
JDK1.8:Lambda表达式
4.64位比32位额外增加10%~30%的内存消耗,1.6提供了普通对象指针压缩功能,但需要更多代码
第二章 java内存区域与内存溢出异常
1.运行时数据区
1.1程序计数器:当前线程执行的字节码的行号指示器,线程私有,没有OutOfMemeryError(OOME)异常
*如果执行的是java方法,计数器记录的是正在执行的虚拟机字节码指令的地址;如果执行的是Native方法,计数器为空
1.2虚拟机栈:用于存储局部变量表、操作数栈、动态链接、方法出口,线程私有,StackOverFlowError(SOFE)、OOME
1.3本地方法栈:执行Native方法,OOME、SOFE
1.4堆:存放对象实例,线程共享,可连续、可不连续,GC的主要区域,-Xmx堆的最大大小 -Xms堆的初始大小,OOME
1.5方法区:存储类信息、常量、静态变量,即使编译器编译的代码,线程共享,永久代,可不连续,OOME
1.6运行时常量池:存编译期生成的字面量和各种引用,运行期间也可能存常量,如String的intern(),OOME
1.7直接内存:1.4中加入了NIO类,引入了一种基于通道和缓冲区的IO方式,他可以使用Native函数库直接分配堆外内存,然后通过java堆里的DirectoryByteBuffer对象最为这块内存的引用,避免在java堆和Native堆之间来回复制
2.对象的创建(new 反射 克隆 反序列化)
虚拟机接到new–>检查是否被加载过–>没有就加载–>分配内存
如果内存规整,即占用的内存在一边,空闲的在另一边,指针在分界点,分配内存就是移动指针,分配内存称为“指针碰撞”
如果不规整,维护一个列表,分配空间给对象实例,然后更新列表,称为“空闲列表”
java堆是否规整由GC器是否带有压缩整理功能
分配完之后初始化为0值
3.对象的内存布局:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)
3.1对象头:第一部分用于存储对象自身的运行时数据,另一部分是类型指针确定对象是哪个类的实例
3.2实例数据:对象存储的有效信息
3.3对齐填充没意义,起占位符的作用
4.对象的访问定位:句柄、直接指针
句柄:在堆里划出一部分内存作为句柄池,对象名指向句柄,句柄包含对象实例数据和类型数据的地址信息
*优点:GC时对象位置移动时,不用改引用
直接指针:对象名指向new
*优点:速度快
5.线程请求的栈深度大于虚拟机允许的最大深度,抛StackOverFlowError
虚拟机栈在扩展栈时无法申请到足够的内存空间,抛OutOfMemeryError
*单线程下,无论栈太小还是内存不足,都抛StackOverFlowError
第三章 垃圾收集器与内存分配策略
1.判断对象存亡方法
1.1.引用计数法
给对象添加一个引用计数器,每当有一个地方引用它,就加1,引用失效,就减1,为0时,对象不能再使用很难解决互相引用的问题
1.2.可达性分析算法
通过一系列被称为“GC Roots”的对象作为起点,当一个对象到GC Roots没有任何引用链时,该对象不可用
*GC Roots包括:虚拟机栈中引用的对象;方法区中类静态属性引用的对象;方法区中常量引用的对象;本地方法栈中JNI引用的对象
2.引用
强引用(GC不会回收)、软引用(有用但非必须)、弱引用(只能活到下次GC前)、虚引用
3.GC过程
可达性分析后没有引用链–>标记并筛选–>筛选条件是该对象是否有必要执行finalize()方法–>对象没有覆盖finalize()方法或已经被虚拟机调用过,则没必要执行finalize()–>有必要执行,把对象放入F-Queue队列,稍后执行一个虚拟机自动建立的,低优先级的Finalizer线程,去触发finalize()方法–>GC对对象第二次标记–>如果二次标记前被引用过,就死不了,否则被回收
4.GC算法
4.1.标记-清除算法:*缺点:效率低;产生不连续的内存碎片
4.2.复制算法:分代算法
4.3.标记-整理算法:标记后,让存活的向一段移动,其他的清掉,保证内存连续
5.何时何地GC
5.1.安全点:程序执行到安全点时才能执行GC
*选择标准:可以让程序长时间执行的地方
主动式中断:GC需要中断线程的时候,不去直接对线程操作,而是设置一个标志,线程轮询这个标志,标志为真时自己中断
5.2.安全区域:一段代码片段中,引用关系不会发生改变,在这里GC是安全的
6.分配策略
优先进入Eden;
大对象直接进入老年代;
年龄到一定程度(默认15岁)进入老年代;
survivor中相同年龄所有对象大小的和大于等于survivor的一半,这些对象以及比它们年龄大的对象进入老年代
第六章 类文件结构
1.Class文件是一组以8位字节为基础单位的二进制流,各个数据项目紧密排列,没有分隔符
伪结构:无符号数和表
2.(未完待续)
第七章 虚拟机类加载机制
1.把描述类的数据从Class文件加载到内存,对数据进行校验,转换解析,初始化,最终形成虚拟机直接使用的java类型
2.通过子类引用父类的静态字段,不会导致子类初始化;通过数组定义来引用类,不会初始化;常量在编译阶段就进入常量池,不会引起初始化
3.比较两个类相等,只有这两个类是由同一个类加载器加载的才有意义。
4.启动类加载器Bootstrap ClassLoader、扩展类加载器Extension ClassLoader、应用程序类加载器Application ClassLoader
5.双亲委派模型,父子关系由组合来实现,一个类加载器接受请求后,先请求父加载器,最终传送到启动加载器,只有当父类解决不了,才由子类自己加载
第八章 虚拟机字节码执行引擎
1.执行引擎执行java代码有两种方法:解释执行(通过解释器执行),编译执行(即时编译器产生的本地代码执行)
第十章 早期优化
1.泛型包括:泛型类、泛型接口、泛型方法
2.两个方法名和参数相同,返回值不同,也可以存在一个Class文件中
3.自动装箱的陷阱
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
c == d; // true e == f; // false Integer在没有基本运算的状态下,不会自动拆箱,范围是-128~127
c == (a + b); // true c.equals(a + b); // true
g == (a + b); // true g.equals(a + b); // false 类型不同
第十二章 晚期优化
1.即时编译器:在运行时,虚拟机将代码编译成与本地平台相关的机器码,并进行各种层次的优化