1. Java基础

一、Java

1.1语言特性

1.1.1类继承

1.1.2泛型

1.1.3多线程

syni

volatie

TLAB:全程时Thread Local Allocation Buffer即线程本地分配缓存,是一个线程专用的内存分配区域,是为了加速对象分配而生的,每一个线程都会产生一个TLAB,该线程独享的工作区域,java虚拟机使用这种TLAB区来避免多线程冲突问题,提高了对象分配的效率。TLAB空间一般不会太大,当大对象无法在TLAB分配时,则会直接分配在内存上。

  • 实现方式
    • 1.继承Thread类,重写run函数
    • 2.实现runnable接口,重写run函数
    • 3.实现callble接口,重写call函数
  • 区别
    • 1.Runable可以提交给Thread来包装,直接启动到一个线程来执行,而Ca而Callable是交给ExecuteService来执行的
    • 2.Callable任务执行后可以返回值,而Runnable不能返回值
    • 3.Callable可以拿到一个Future对象,表示异步执行计算的结果。
  • 线程池-> Executor提供四种线程池
    • 1.newCachedThreadPool通用缓存,灵活回收空间空闲缓存
    • 2.newFixThreadPool定义线程池,超出线程池在队列中等待
    • 3.newSingleThreadPool单线程线程池,保证指定顺序FIFO,LIFO,优先
    • 4.newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

1.1.4反射

Class类
Class.forName("类的全称")

  • 不仅代表了类的类型,还代表了动态加载类
  • 编译时刻加载类是静态加载类,运行时刻加载类是动态加载类

1.1.5序列化

1.1.6封装类

1.1.7引用

  • 强引用:new一个Object存放在堆内存,然后用一个引用指向它,这就是引用。如果一个对象具有强引用,那垃圾回收器不会回收它,当内存空间不足时,Java虚拟机会抛出OutOfMemoryError错误,使程序异常终止,而不会随意回收具有强引用的对象来解决内存不足的问题。
  • 弱引用:如果一个对象只具有软引用,则内存空间足够时,垃圾回收器不会回收它,如果内存空间不足时,就会回收这些对象,只要垃圾回收器没有回收只具有软引用的对象,改对象就可以被程序所使用,软引用可以用来实现内存敏感的高速缓存。
  • 软引用:只具有软引用拥有更短的生命周期,每次执行GC时,一旦发现了只具有软引用的对象,不管当前内存足够与否,都会回收内存。不过由于回收器是一个优先级很低的线程,因此不一定会很快发现只具有软引用的对象
  • 幻影引用(虚引用):虚引用并不会决定对象的生命周期,如果一个对象仅持有虚引用,在任何时刻都可能会被垃圾回收器回收,虚引用主要用来跟踪对象被垃圾回收器回收的活动。

1.2类库

1.2.1集合

java中集合为value,key-value两种,存储的又分为List,Set,

  1. List是有序的,可重复的
  2. Set是无序的不可重复的,根据equals和hashcode判断,如果要用contain判断对象是否存在set中必须重写hashcode方法

存key-value为map

  1. ArrayList跟LinkedList的区别:ArrayList底层实现的是数组,LinkedList底层实现的是链表
  2. HashMap跟HashTable的区别:1.HashMap跟HashTable都可以用key-value存储数据,2.hashMap允许把null作为key或者value,HashTable不可以。3.HashMap是线程不安全的,效率高,HashTable是线程安全的,效率低。

1.2.2流

IO/NIO
IO类型

  • 同步阻塞
  • 同步非阻塞
  • 基于信号
  • 多路复用
  • 异步IO

二、JVM

  • 类加载子系统:负责从文件系统中或者网络中加载Class信息,加载的信息存放在一块称为方法区的内存空间

  • 方法区:就是存放类信息、常量信息、常量池信息、包括字符串字面量和数字常量等。

  • Java堆:在Java虚拟机中启动的时候建立java堆,他是java程序最主要的内存工作区域,几乎所有的对象实例都存放在java堆中,java堆是所有线程共享的。

  • 直接内存:Java的NIO库允许java程序使用直接内存,从而提高性能,通常直接内存速度会优于java堆,读写频繁的场合会考虑使用。

  • java栈:每个虚拟线程都会有一个私有的栈,一个线程的java栈在线程创建的时候会被创建,java栈中保存着局部变量、方法参数,同时java方法的调用、返回值等。

  • 本地方法栈:基本与java栈一致,最大的区别是,本地方法用于本地方法调用,java虚拟机允许java直接调用本地方法,通常使用c语言编写

  • 垃圾回收系统:是java的核心,java有一套自己进行垃圾清理的机制

  • PC寄存器是每个线程私有的空间,java虚拟机会为每个线程创建PC寄存器,在任意时刻,一个java线程总是在执行一个方法,这个方法被成为当前方法,如果当前方法不是本地方法,PC寄存器就会执行当前正在被执行的指令,如果是本地方法,则PC寄存器的值为undefined,寄存器存放当前执行环境指针,程序计数器,操作栈指针,计算变量指针等信息。

  • 执行引擎:负责执行虚拟机的字节码,一般先编译成机器码,在执行。


    jvm结构.png

2.1. 类加载子系统

负责从文件系统中或者网络中加载Class信息,加载的信息存放在一块称为方法区的内存空间


双亲委派
OSGI

java对象生命周期

  • 创建阶段
  • 应用阶段
  • 不可见阶段
  • 不可达阶段
  • 收集阶段
  • 终结阶段
  • 对象重新分配阶段

2.2. java堆

在Java虚拟机中启动的时候建立java堆,他是java程序最主要的内存工作区域,几乎所有的对象实例都存放在java堆中,java堆是所有线程共享的。


java堆是java应用程序关系最密切的内存空间,几乎所有对象都是存放在其中的,并且java堆完全是自动化管理的,通过垃圾回收机制,垃圾对象会自动清理,不需要显示地释放。
根据垃圾回收机制不同,java堆可能拥有不同的结构,最为常见的就是将整个java堆分为新生代和老年代。其中新生代存放着新生对象或者年龄不大的对象,老年代则存放老年对象。

新生代分为eden区、s0区、s1区,其中s0和s1区经常被称为from,to区,他们是两块大小相等,并且可以互换角色的空间。

绝大多数情况下,对象首先分配在eden区,在一次新生代回收之后,如果对象还活着,则进入s0 或者 s1区,之后每经过一次垃圾回收,如果对象还存活,则他的年龄就增加1,当对象达到一定年龄之后,则进入老年代。

2.3. java栈

每个虚拟线程都会有一个私有的栈,一个线程的java栈在线程创建的时候会被创建,java栈中保存着局部变量、方法参数,同时java方法的调用、返回值等。


Java栈是一块线程私有的内存空间,一个栈,一般由三个部分组成:局部变量表、操作数栈、帧数据区。

  • 局部变量表:用于报错函数的参数和局部变量
  • 操作数栈: 主要保存计算过程的中间结果,同时作为计算过程中变量的临时存储空间。
  • 帧数据区:java栈需要一些数据来支持常量池的解析,这些帧数据区保存着访问常量池的指针,方便程序访问常量池,另外,当函数返回或出现异常时,虚拟机必须有一个异常处理表,方便发送异常的时候找到异常的代码,因此异常处理表也是帧数据区的一部分。

2.4. 方法区

就是存放类信息、常量信息、常量池信息、包括字符串字面量和数字常量等。


java方法区和堆一样,方法区是一块所有线程共享的内存区域,它保存系统的类信息,比如类的字段、方法、常量等。方法区的大小决定了系统可以保存多少类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出的错误,方法区可以理解为永久区(Perm java1.8已移除)

2.5. 垃圾回收器

是java的核心,java有一套自己进行垃圾清理的机制


JVM结构、GC工作机制详解,GC有两点:

  • 1.GC是负责回收所有无任何引用对象的内存空间。垃圾回收的是无任何引用的对象占据的内存空间而不是对象本身。
  • 2.GC回收机制的两种算法
    • a.引用计数法
    • b.可达性分析算法
2.4.1 垃圾回收算法
  1. 引用计数法:这是一个比较经典的垃圾回收算法,其核心是在对象被其他所引用时计数器加1,而当引用失效的时候减1,有个严重的问题:无法处理循环引用的情况,还有就是每次进行加减操作比较浪费系统性能。

  2. 标记清除法:分为标记和清除两个阶段进行处理内存中的对象,这个方法有个很大的弊端,就是空间碎片的问题,垃圾回收后,空间不是连续的,不连续的内存空间工作效率会低于连续的内存空间。

  3. 复制算法:其核心是将内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中存留的对象复制到未使用的内存块中,之后去清除之前正在使用的内存块中所有的对象,反复去交换两个内存角色,完成垃圾收集。(java新生代的from to 就是使用这个算法。)

  4. 压缩标记法:压缩标记法在标记清除法基础上做了优化,把存活的对象压缩到内存一端,而后进行垃圾清理(java老年代使用的就是这个算法)

  5. 分代算法:就是根据对象特点把内存分为N块,而后根据每个内存特点使用不同的算法,对于新生代老年代来讲,新生代回收频率很高,但是每次回收耗时很短,而老年代回收频率较低,但是耗时较长,所以应该尽量减少老年代的GC。(体现新生代老年代)

  6. 分区算法:将整个内存分为N个小的空间,每个小空间都可独立使用,这样细粒度的控制一次回收小空间,而不是对整个空间进行GC,从而提升性能,并减少GC停顿时间。(1.7以后新提出)

2.4.2 垃圾回收器

在java虚拟机中垃圾回收器不仅仅只有一种,什么情况下使用哪一种,对性能又有什么影响,都是我们应该了解的


1. 串行垃圾回收器(serial)

是指单线程进行垃圾回收的回收器,每次回收时,串行回收器只有一个工作线程,对于并行能力较弱的计算机来说,串行回收器的专注性和独占性拥有更好的性能表现。串行回收器可以在新生代和老年代使用,根据作用于不同的堆空间,分为新生代串行回收器和老年代串行回收器。

2. 并行垃圾回收器(ParNew)

在串行回收器的基础上进行了优化,他可以使用多个线程同时进行垃圾回收,对于性能较强的计算机而言,可以有效的缩短垃圾回收所需的实际时间。
ParNew回收器是一个工作在新生代的垃圾回收器,他只是简单的将串行回收器多线程化,回收策略和算法跟串行回收器一样。

新生代ParallerGC回收器,使用了复制算法的收集器:也是多线程独占形式的收集器,但ParallerGC有个非常重要的特点,就是它非常关注系统的吞吐量。(1.8默认)

老年代ParallerOldGC回收器也是一种多线程回收器,和新生代ParallerGC回收器一样,也是一种关注吞吐量的回收器,它是使用标记压缩算法进行实现。

3. CMS回收器

CMS全称是Concurrent Mark Sweep是并发标记清除,使用的是标记清除算法,主要关注系统停顿时间。
CMS并不是独占的回收器,也就是说CMS回收的时候,应用程序仍在不停工作,又会有新的垃圾产生。

4. G1回收器

G1回收器(Garbage-First)是在jdk1.7提出的垃圾回收器,长期目标来看是为了替代CMS回收器,G1回收器拥有独特的垃圾回收策略,G1回收器属于分代垃圾回收器,区分新生代和老年代,依然有eden和from/to区,并不要求整个eden区或者新生代、老年代空间都连续,它使用了分区算法。(1.9默认)

  • 并行性: G1回收期间可以多线程同时工作。
  • 并发性: G1拥有与应用程序交替执行的能力,部分工作可与应用程序执行,在整个GC期间不会完全阻塞应用程序。
  • 分代GC:G1依然是一个分代的收集器,但是它是兼顾新生代老年代一起工作的,之前的垃圾收集器往往在新生代工作或者在老年代使用,因此这是一个很大的不同。
  • 空间整理:G1在回收过程中,不会像CMS那样若干次GC工作后,需要进行碎片整理,G1使用了有效复制对象的方式,减少空间碎片。
  • 可预见性:由于分区的原因,G1可以只选取部分区域进行回收,缩小了回收的范围,提升了性能。
2.4.3 常见问题

垃圾回收时的停顿现象:
垃圾回收器的任务是识别和回收垃圾对象进行内存清理,为了让垃圾回收器可以搞笑的执行,大部分情况下,会要求系统进入一个停顿的状态,停顿的目的是终止所有的线程,这样系统才不会有新的垃圾产生,同时停顿保证了系统在某一瞬间的一致性,也有益于更好的标记垃圾对象,因此在垃圾回收时,都会产生应用程序的停顿。

2.6. 本地方法栈

基本与java栈一致,最大的区别是,本地方法用于本地方法调用,java虚拟机允许java直接调用本地方法,通常使用c语言编写


2.7.直接内存

Java的NIO库允许java程序使用直接内存,从而提高性能,通常直接内存速度会优于java堆,读写频繁的场合会考虑使用。


直接内存也是java程序中非常重要的组成部分,特别广泛应用在NIO中,直接内存跳过了Java堆,使java程序可以直接访问原生堆空间,因此在一定程度上加快了内存访问速度。

2.8.PC寄存器

PC寄存器是每个线程私有的空间,java虚拟机会为每个线程创建PC寄存器,在任意时刻,一个java线程总是在执行一个方法,这个方法被成为当前方法,如果当前方法不是本地方法,PC寄存器就会执行当前正在被执行的指令,如果是本地方法,则PC寄存器的值为undefined,寄存器存放当前执行环境指针,程序计数器,操作栈指针,计算变量指针等信息。


2.9.执行引擎

负责执行虚拟机的字节码,一般先编译成机器码,在执行。


三、目录

目录
下一篇:2. 设计模式与架构

你可能感兴趣的:(1. Java基础)