01 Java基础

本文探讨了Java内存模型的五部分结构,元空间的变化,以及ArrayList、LinkedList、HashMap、HashTable和ConcurrentHashMap的区别。重点讲解了垃圾回收机制和引用计数器与可达性分析算法。同时,分析了不同数据结构在性能上的特点和垃圾回收在程序中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Java的内存模型

1.1 JVM内存模型

jvm内存模型主要分为五个区域,分别是:一个计数器两个栈一个区一个堆,一器两栈一堆一区

  1. 程序计数器:记录当前线程执行到的字节码的行号
  2. 虚拟机栈:存放方法运行时需要的数据例如局部变量,称为栈桢
  3. 本地方法栈:可以理解为方法在这里注册的,虚拟机栈是为了方法能够执行,本地方法栈是为了能够找到方法
  4. 方法区:线程共享,存放运行时常量池、已被虚拟机加载过的类信息、静态常量等
  5. 堆:存储对象的实例

在这里插入图片描述

在这里插入图片描述

1.2 元空间和永久代

Metaspace元空间

永久代是JDK1.7及之前的称呼,位于堆中

1.8之后,永久代移动到了方法区中,同时改名为元空间

JDK1.7之前,堆内存被划分为三块区域:新生代、老年代、永久区。注意是1.7及之前!!!
新生代对象进入老年代的条件

  1. 设置了-XX:PretenureSizeThreshold3M 参数,大于3M的对象进入老年代
  2. 设置了-XX:MaxTenuringThreshold,熬过了x次Minor GC的对象进入老年代
  3. 如果在Survivor空间中相同年龄所有对象对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold要求的年龄
  4. 空间分配担保机制:当Minor GC时,新生代存活的对象大于Survivor的大小时,这时一个Survivor装不下它们,那么它们就会进入老年代。
    在这里插入图片描述

1.8之后,把存放元数据(类的Method、Field等)的永久代挪到了方法区中,同时改名为元空间

在这里插入图片描述

还有,字符串常量池1.6之前存放在方法区中,1.7及之后就存放在堆中了

方法区用的是本地内存,堆用的是JVM内存

2. 集合

2.1 ArrayList和LinkedList的区别

  1. ArrayList的实现基于数组,LinkedList实现基于双向链表
  2. 对于随机访问,ArrayList效果较好,因为有索引;对于插入和删除LinkedList效果好,因为LinkedList没有索引
  3. LinkedList比ArrayList更加占内存,因为LinkedList的节点Node除了要存储数据,还得存储两个引用,一个只想前一个元素,一个指向后一个元素

2.2 HashMap、HashTable、ConcurrentHashMap的区别

在这里插入图片描述

HashMap

  1. 基于哈希表实现,数组+链表+红黑树;当哈希桶大小超过64且链表长度超过8才会从链表转为红黑树,否则只会扩容
  2. 线程不安全,原因:1.7之前扩容时覆盖,在链表头部插入数据时死循环;1.8由transfer方法改为resize后只会覆盖数据
  3. 键和值都可以为null

HashTable

  1. 也是基于Hash表实现,数组+链表来解决哈希冲突
  2. 线程安全,所有的方法都通过Synchronized加锁,导致效率低下
  3. 键和值都不能为null

ConcurrentHashMap

  1. 1.7之后数据结构和HashMap一致

  2. 线程安全,通过key的hash值计算出数组的索引,如果这里没有Node,则使用CAS尝试插入元素,失败则无条件自旋,直到插入成功;如果有Node,则使用Synchronized锁住该Node,再执行插入操作。

    读操作不加锁,提升了效率

  3. 键和值都不能为null

2.3 HashMap和TreeMap的区别

  1. HashMap基于哈希表实现,创建的时候可以调优初始容量和负载因子;TreeMap基于红黑树实现,没有调优选项,因为该树总是处于平衡状态
  2. HashMap适用于在Map中插入、删除和定位元素;TreeMap适用于按照自然排序或者自定义顺序遍历元素。HashMap通常比TreeMap快一点,数据结构使然,建议多使用HashMap,在需要用到排序的时候再使用TreeMap
  3. TreeMap实现了SortMap接口,默认按照键的升值进行排序,也可以自定义排序的比较器。

3. 垃圾回收

创建各种引用数据类型的变量的时候,虚拟机都会在堆中开辟一块内存空间用于存放;当这块内存空间不再被任何变量引用的时候,这块内存就变成了垃圾

Java引入了了垃圾回收机制Garbage Collection,GC;用来处理垃圾,不需要我们手动的区释放空间

可以手动使用System.gc()方法,通知GC执行,但是GC不是一定会执行

Object类中的finalize()方法,当对象被回收之前会执行该方法;但是如果程序运行结束之前,虚拟机没有进行垃圾回收,那么finalize()将会没有机会被执行

垃圾回收两种算法

  1. 引用计数器算法

    1. 在类中创建一个程序计数器,每当类第一次被创建为对象时,将计数器设为1

    2. 如果有新的引用指向该对象,计数器+1;失去一个引用,计数器—1

    3. 当计数器变为0,该对象就可以被回收

      在这里插入图片描述

  1. 可达性分析算法

    1. 当我们创建对象的时候,GC就会开始监控对象,通过有向图的方式记录和管理堆中的所有对象

    2. 从一个根节点GC ROOT开始,依次向下寻找对应的引用的节点,所寻找的路径称为引用链

    3. 当一个对象没有任何引用链与GC链接的时候,就可以被回收了

      在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值