JVM

1内存模型

1.1方法区

  • 存储着static final常量,类的信息,静态变量,最重要的是常量池:存放编译后生成的字面量(文本字符串,final的常量)和符号引用。String类的intern方法可以向常量池增加信息。

1.2Java堆

具体内存设置参数

  • 常见设置参数
    • -Xms 初始堆大小
    • -Xmx 最大堆大小
    • -Xmn 年轻代=eden+survivor
    • -XX:PermSize 持久代初始大小
    • -XX:MaxPermSize 持久代最大值
    • -XX:NewRadio 老年代与年轻代比值
    • -XX:SurvivorRadio Eden与Survivor比值
    • -XX:MaxTenuringThreshold 进入老年代Age年龄设置
    • -XX:PretenureSizeThreshold 对象多大直接分配老年代
    • -XX:HandlePromotionFailure 是否允许担保失败
  • 存放用户生成的对象实例
  • 分区:多种分法,分为新生代,老年代;新生代有Eden空间和两个Survivor空间。如果开启TLAB那么还会分为多个线程私有的分配缓冲区。

1.3程序计数器

  • 虚拟机多线程是切换轮流执行,需要程序计数器记录切换后的执行位置

1.4本地方法栈

1.5Java虚拟机栈

  • 每个方法执行时就会创建一个栈帧包含:

    • 1.局部变量表:编译器可知的基本数据类型,对象引用,局部变量表中的变量没有初始值。
    • 2.操作数栈
    • 3.动态链接:存放指向方法的引用,符号引用转换为直接引用的时间不同分为静态链接和动态链接。

      • 解析调用:类加载阶段进行:方法程序在真正运行之前就有一个可以确定的版本,在调用时期不可变,即编译期可知,运行时期不可变。主要分为两大类:静态方法,私有方法,实例构造器,父类方法,fianl方法
      • 静态分派:依赖静态类型,编译期可得
      • 动态分派:根据实际类型。
    • 4.方法出口

1.6直接内存

是JavaNIO使用的缓存区域,可以直接在堆外内存中分配,可以使用反射unsafe类来获得。

2垃圾回收

2.1判断是否需要回收

1.是否有引用,无法解决相互引用问题

2.可达性分析根有四个:

  • 虚拟机栈中的本地变脸表中引用的
  • 方法区中的静态属性的对象
  • 方法区中常量应用的对象
  • 本地方法栈中引用的对象

2.2垃圾收集算法

  1. 标记清除法:碎片 老年代
  2. 复制算法:空间浪费 新生代
  3. 标记整理:老年代

2.3 何时回收

安全点:抢先式中断和主动式中断
安全区域:在代码片段中不会引起引用发生变化的时候

2.4垃圾回收器(主要是CMS和G1)

CMS:

  1. 初始标记(停顿)只标记根直接引用的
  2. 并发标记 tracing
  3. 重新标记(停顿)之前改动过的
  4. 并发清除

占用CPU,每次清理有残余的浮动垃圾,标记清除算法有碎片

G1:

特点:
最重要的改进,对堆进行了分区,避免全堆停止;
维护一个有限列表根据算法确定回收价值最大的区域;
使用一个set记录不同区的对象,避免全堆扫描

优势:
1. 并发
2. 分代
3. 空间整合:因为标记整理
4. 可预测停顿:分区了,可以选择一定的分区回收

过程:

  1. 初始标记(停顿,跟CMS一样)
  2. 并发标记
  3. 最终标记(停顿,根据log更新标记)
  4. 筛选回收(停顿,制定回收分区所以时间可控)

2.5内存分配策略

  • 优先分配Eden区
  • 设置超过年龄进入老年代
  • 大对象直接进入老年代
  • 分配担保策略

3实战ecplice调优(加深理解)

  • Java运行时编译
  • 增加Eden区的大小,减少MinorGc次数
  • 增加老年代大小,减少FullGC次数

4类加载机制

4.1加载

  • 双亲委派机制
  • 加载器分为:启动类加载器,扩展类加载器,应用程序类加载器
  • 使用组合方式来复用父类加载器代码
  • 这样加载类的时候会有一种优先级的区别,类加载器加载类时首先先让父类去加载,然后再自己加载
  • 双亲委派机制破坏
  • JNDI
  • 动态语言支持,热插拔

4.2验证

4.3准备

类变量(static修饰的,final static修饰的是给定的值)赋初始值,分配在方法区中,实例变量赋值。

4.4解析

将符号引用转换问直接引用。(像是老师点名记录学生坐在哪里)

4.5初始化

  • 五种情况:
  • 1.new,设置、读取静态字段,访问静态方法
  • 2.反射调用
  • 3.初始化子类时父类为初始化,但是接口是不同的。
  • 4.加载main()
  • 5.动态语言支持的MethodHandle实例

  • 误区:

  • 1.子类调用继承的静态字段和静态方法不会初始化子类。
  • 2.数组定义引用类不会导致类初始化。
  • 3.常量引用不会导致初始化。

  • 顺序

  • 搜集顺序是按照源文件顺序,静态语句块中的语句只能赋值后面的类变量,不能访问。
  • 父类先于子类运行
  • 是线程安全的,同一个类加载器对同一个类只加载一次

4.6字节码和动态代理技术

需要一个接口,被代理的类继承这个接口,创建实现InvocationHandler的动态代理类,实现里面的invoke(Object proxy,Method method, Object[] args)方法。调用NewProxyInstance();每一个方法,都会调用invoke方法,这样可以实现切面编程AOP

5语法糖

1.伪泛型

在源代码中的泛型,在code属性中的字节码删除,但是元数据中还是保留了。
2.自动装箱,拆箱
3.foreach循环遍历

6逃逸分析

分析对象动态的作用域,如果对象在方法中定义之后被外部的方法引用叫方法逃逸,类似还有线程逃逸。对于未逃逸的对象我们可以采用一些办法加快运行速度:1.栈上分配,2.同步消除,3.标量替换

7高效并发

7.1Java内存模型

线程,工作内存,save和load操作,主内存

7.2volatile

使用场景:

  • 运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值。
  • 变量不需与其他的状态变量共同参与不变约束。

作用:

  • 新值能立即同步到主内存,每次使用前从主内存刷新。保证多线程操作时的可见性。
  • 避免指令重排序。

原子性

可见性

  1. volitaile
  2. synchronized 利用lock和unlock
  3. final初始化时就确定了。

有序性

  1. volitaile和sychronized

7.3现行并发原则

  1. 同一线程内前面的操作一定先行并发生与后面的。
  2. unlock一定线性发生于后面对同一个锁的lock
  3. volatile变量的写操作先行发生于后面对这个变量的读
  4. 线程启动
  5. 线程终止前运行完该线程所有代码
  6. interrupt()先行发生于检测到的中断事件发生
  7. 对象初始化发生于finalize()方法之前
  8. 传递性

7.4线程调度

线程调度分为两种:协同式,抢占式

Java通过映射到系统的原生线程来实现线程调度和优先级分配

线程的状态转换

  1. 新建
  2. 运行start()
  3. 阻塞 同步的时候
  4. 无线等待 wait()join()
  5. 限期等待 sleep()设置了事件的timeout的wait()join()
  6. 结束 跑完了

8线程安全

8.1线程安全的实现方法

  1. 互斥同步:sychronized,J.U.C下面的ReentrantLock(多个condition,公平锁,等待中断)
  2. 非阻塞同步,CAS根据类似版本号。J.U.C包里面的compareAndSet()和copareAndSwapLong()
  3. ThreadLoacal类,为每一个线程提供一个单独的变量副本

9锁优化

9.1适应性自旋锁

主要目的是消除,挂起然后重新启动的时间。
自适应是动态的判断自旋的循环次数,减少CPU自旋的时间开销

9.2锁消除

如果堆上的所有数据都不会被其他线程访问到,那就可以当作栈上的数据对待不用加锁。
字符串想加:s1+s2+s3;

9.3锁粗化

减少互斥操作的开销,多个小的锁合并成一个大的锁

9.4轻量级锁

  • 加锁:检查对象头存储标志位是否为01,加锁时将栈帧中的锁记录空间存储目前对象的对象头拷贝,然后通过CAS操作将对象头更改为指向锁记录的指针。并且标志位变为00
  • 失败:检查对象是否指向栈帧。不,则将锁标志位更改为10变为重量级锁,然后线程挂起。
  • 解锁:CAS进行替换如果替换成功则完成,否则,释放锁还需唤醒挂起线程

9.5偏向锁

在执行过程中一直保持无锁状态知道有其他线程介入。
标志位设置为01,将对象头记录为获取对象线程的ID,同一个线程进入对象不作任何同步操作。其他线程进入则根据锁定状态,如果未锁定撤销偏向恢复01,或者进入轻量级锁(00)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值