记录一些知识点,积累起来
java代码执行方式
1.java源码-》编译 class-》classloader加载-》执行(解释或者编译执行),其中编译执行分为client模式和server模式;
class文件不仅仅包含字节码,也包含了辅助JVM执行class的附加信息
结构信息:版本号 大小等信息
元数据:变量和声明之类
方法信息:源码中语句和表达式的对应项,字节码、异常处理表等
class文件是一个完整的自描述文件,字节码只是其中很小的一部分,源码编译为class后即可放入jvm执行,通过classloader来加载(类加载机制)。
2.类加载机制,将class文件生成对象的过程(过程可能理解不对,而应该理解为一种机制)。
加载机制的特点:
1.动态特性;可以从远程下载加载
2.隔离特性,比如一个vm中有多个应用,应用之间相互隔离。
JVM类加载有三个步骤:装载load-》link-》init(非必须)
java开发人员调用class.forName来构建类对象的时候,使用类的classloader来加载。JVM为了保护加载、执行类的安全,不允许classloader直接卸载所加载的类,必须由jvm来执行卸载操作。在sun jdk中,如果对应的classloader没有加载类的引用,则classloader加载的类才进行卸载(marked-sweep)。
JVM指令执行基于栈的体系结构(为什么以栈?)。线程在创建后,PC 指向下一条指令要执行的位置。栈中存放了栈帧(stack Frame),可以理解为每一个方法都是一个栈帧,栈帧之中有局部变量区和操作数栈两部分(也有一些杂用空间),操作数栈用来存放计算的中间结果。当方法执行结束,则会有对应的标记,JVM垃圾回收机制会来回收该区域。
解释执行的效率比较低,所以sun jdk提供将字节码编译为机器码的支持,而且只在执行的时候进行,称为JIT编译器(JUST IN TIME)。对于一些高频的执行的代码则采用该方案,故java的虚拟机也叫做Hotspot Vm。非高频代码,则依然按照解释方式执行。
编译执行,分两种模式:client 和 server
client compiler 简称c1,轻量级,一般用于桌面程序
server compiler 简称c2,重量级,一般用于服务端,侧重全局优化,包括监控运行时信息。
逃逸分析是C2做很多优化的基础,所谓逃逸分析是根据运行状态判断方法中的变量是否会被外部读取,如果不会则认为该变量是逃逸的。
**c1与c2是对方法体入口的优化
OSR(on stack Replace),只替换循环体入口的代码。需要达到一定的参数条件才进行JIT编译。**
2.内存回收
算法:1.copy 2. mark-sweep 3.mark-compact
sun jdk认为大部分的对象的生命周期都是短暂的,所以将内存区进行分段。young generation and old generation,对于不同的分段采用不同的GC。
young generaion 分为:Eden 区 S0 区 S1区,其中S0、S1也称为From 区 To区,这么称呼的原因在于新生代的GC主要采取的是Copying算法,从Eden区copy数据到S0,从S0到S1。对于新生代对象所占区域进行GC也称为minor GC。
串行GC
并行回收GC(paraller scavenge)
并行GC(CMS,concurrent mark-sweep GC)
JMX(java manager Extensions)
3.异常处理机制
分为检查型异常和非检查型异常,顾名思义,检查型异常是可以检查得出来的,在运行之前就可以被check到,非检查型就是从语法语义等方面无法confirm的异常。
对于检查型异常,必须要用try-catch给包住,保证在可能出现问题的情况下可以处理。一般情况下,对于检查型异常,IDE都会对应的提醒。
非检查型异常,runtimeException和Error。
4.sun jdk类库(分布式与并发)
对于构建分布式应用而言,最重要的是集合、网络、并发、序列与反序列化的包。网络板块取决于网络的协议以及操作系统本身的一些实现方式(牵扯到数据流到各层之间的切换,我不知道这种理解是否正确)。
集合:Collection与Map两种数据结构,Collection存储单个对象,Map存储key-value结构,其中,Collection的实现类有List and set,其中List可以存储重复对象,而set不可以;
List接口的常用实现类:ArrayList,LinkedList,Vector,Stack
Set接口的常用实现:HashSet,TreeSet
注意每一种实现的增删改查的实现效率(具体实现方法),从具体实现方法来判断是否是线程安全的类型。
ArrayList
-非线程安全
-基于数组方式实现
-插入元素时可能要扩容,而删除时不影响大小
LinkedList
基于双向链表机制,以内部的Entry类来代表集合中的元素
-双向链表机制,可以向后遍历也可以向前查找
-非线程安全(获取对象时可能会抛出concurrentModifyException错误)
-插入元素时,会先创建Entry对象,并切换相应元素的前后引用。
Vector
类似于ArrayList,不过在操作时有synchronized关键字,线程安全。
Stack
继承自Vector,但是如其名实现了stack的操作后进先出(LIFO),提供了push pop peek操作。
pop与peek区别下,pop会删除数据结构最后一个元素,peek不会。
HashSet
是set接口的实现,set与list的最明显的区别在于set不允许元素重复。set为了做到不允许重复,是基于HashMap来实现。
-基于HashMap实现
-是非线程安全的
TreeSet
与hashset的显著区别在于对排序的支持,TreeSet基于treeMap实现。(其实从名字也可以看出来,hash是key-value结构,tree是树结构,树结构最大的优点可以构成各种树,什么avl 红黑之类,排序和快速检索)。
-非线程安全
-基于TreeMap实现,支持排序
上面都是collection结构,下面是Map key-value结构。
HashMap
是Map中最常用的,我实际项目中用HashMap用的最多。
HashMap解决Hash冲突的方法是采用链表的方式(不是开放定址)
-hashMap 非线程安全
-遍历不保证顺序
-HashMap 采用数组方式存储key,value构成Entry对象,无容量限制;
-HashMap 在插入元素时可能会扩充数组容量,扩充容量时要重新计算Hash,并复制到新的数组中(这个可以理解,散列的size变了,为了减少冲突应该是要重新hash)
TreeMap
-基于红黑树实现,无容量限制
-TreeMap是非线程安全的
对于各种数据结构的使用,结合各自的数据结构类型与业务场景来使用。