对象内存分配机制与垃圾回收

简介: 本内容介绍了对象内存分配机制与垃圾回收(GC)原理,涵盖对象在堆与栈中的存储、新生代与老年代的GC策略、常见回收算法及回收器特点,适用于Java等语言的内存管理优化。

对象有的存在在栈中

年轻代(伊甸园 s1,s0(8:1:1))fnedai

  • 对象流转过程
  1. 新对象在 Eden 区创建。
  2. Eden 区满时触发Minor GC(新生代垃圾回收),存活的对象被移至 Survivor 区(如 S0)。
  3. 下次 Minor GC 时,Eden 区和 S0 区存活的对象被移至 S1 区,S0 区清空。
  4. 多次 GC 后仍存活的对象(年龄达到阈值,默认 15 次)被移至老年代

避免内存碎片

老年代:

  • 触发 GC 条件:老年代空间不足时触发Major GC/Full GC(全局垃圾回收)。

特殊情况(栈上分配):

逃逸:对象的生命周期完全在方法内部,不会被外部访问。

  • 在某些语言或优化场景下,短期存活的小对象可能被分配到栈上(如 Java 的逃逸分析优化)。
  • 逃逸分析通过识别对象的生命周期范围,将不逃逸的短期小对象分配到栈上,避免 GC 开销,提升性能。

永久代:因为容易发生oom所以移动至方法区的元空间中

为什么大部分对象在堆中?

  • 生命周期灵活性:堆内存允许对象在方法调用结束后继续存在(如返回对象引用)。
  • 共享访问:多个线程可以访问同一对象(需注意线程安全)。
  • 动态内存分配:适合创建大小不确定或需要长期存在的对象。

gc

垃圾回收机制(GC)

1. 垃圾回收算法

  • 标记 - 清除(Mark-Sweep)
    标记存活对象 → 清除未标记对象。缺点:产生内存碎片。
  • 标记 - 整理(Mark-Compact)
    标记存活对象 → 将对象移动到一端 → 清除边界外的内存。避免碎片,但需移动对象,成本高。
  • 复制(Copying)
    将内存分为两块,每次只使用一块。GC 时将存活对象复制到另一块,清空原区域。适用于对象存活率低的场景(如新生代)。
  • 分代收集(Generational Collection)
    根据对象生命周期不同,在新生代和老年代采用不同算法(如新生代用复制算法,老年代用标记 - 整理)。
  • 新生代:复制算法
  • 老年代:标记清除、标记整理

2. 常见垃圾回收器

新生代回收器

  • Serial:单线程,暂停所有用户线程(Stop The World,STW),适合单 CPU 环境。
  • ParNew:Serial 的多线程版本,与 CMS 配合使用。
  • Parallel Scavenge(吞吐量优先):多线程,目标是最大化吞吐量(CPU 用于运行用户代码的时间比例)。
  • 老年代回收器
  • Serial Old:单线程,标记 - 整理算法。
  • Parallel Old:Parallel Scavenge 的老年代版本,多线程标记 - 整理。
  • CMS(Concurrent Mark Sweep):以获取最短回收停顿时间为目标,并发标记和清除,但会产生内存碎片。
  • G1(Garbage-First):分 Region 管理内存,兼顾吞吐量和低延迟,适合大内存场景。
  • ZGC(Z Garbage Collector):极低延迟(亚毫秒级),支持 TB 级内存,JDK 11 + 引入。
  • 全区域回收器
  • Shenandoah:与 G1 类似,但更注重低延迟,通过并发整理减少 STW 时间。
  • Epsilon:实验性回收器,仅分配内存,不执行垃圾回收(用于性能测试)。
相关文章
|
4月前
|
负载均衡 Java Nacos
微服务架构中的服务注册与发现流程
本内容介绍了微服务架构中的服务注册与发现流程,包括服务注册中心(如Nacos)、服务提供者和调用者的角色分工。服务启动时自动注册信息至注册中心,调用者通过客户端负载均衡(如Spring Cloud Loadbalancer)选取服务实例进行远程调用。同时,内容还讲解了OpenFeign的工作原理,其作为HTTP客户端集成负载均衡,通过接口定义、代理生成、请求发送与结果解析,实现服务间的高效通信。
|
4月前
|
消息中间件 NoSQL Java
延时实现
本节介绍了多种关闭过期订单的实现方案,包括定时任务、JDK延迟队列、Redis过期监听、Redisson延迟队列、RocketMQ延迟消息及RabbitMQ死信队列。各自优缺点明显,适用于不同业务场景,如定时任务适合小数据量,RocketMQ适合高并发解耦场景,而Redisson则使用简单且高效。选择时需综合考虑系统复杂度、数据量及可靠性要求。
|
4月前
|
负载均衡 网络性能优化
了解EMQ
EMQ通过MQTT协议的QoS机制保障消息可靠传输,支持QoS 0、1、2三个等级,分别实现消息最多一次、至少一次和恰好一次传递。对于延迟消息,EMQ X支持通过特殊主题前缀`$delayed/{DelayInterval}`实现延迟发布。点对点通信可通过不带群组的共享订阅(如`$queue/t/1`)实现,结合负载均衡策略如随机、轮询等,确保消息仅由一个订阅者接收;发布订阅模式则通过带群组的共享订阅(如`$share/组名称/t/1`)实现,确保每组一个订阅者收取消息。
|
4月前
|
消息中间件 存储 缓存
再次了解kafka
Kafka通过offset机制解决消息重复消费问题,支持手动提交偏移量及唯一ID去重。它保证分区内的消息顺序消费,结合集群、副本与重平衡实现高可用。高性能设计包括顺序读写、分区、页缓存、零拷贝等。数据清理依赖保留时间或大小策略,点对点和发布订阅模式则通过消费者组实现。
|
4月前
|
存储 缓存 Linux
CPU上下文切换的原理及其在系统调用和进程切换中的应用
本内容深入解析了CPU上下文切换的原理及其在系统调用和进程切换中的应用。详细说明了CPU寄存器、程序计数器在任务切换中的作用,以及系统调用与进程上下文切换的区别。同时探讨了上下文切换带来的性能开销,涉及TLB和虚拟内存管理机制,帮助理解操作系统如何高效调度进程。
|
4月前
|
存储 算法 Sentinel
熔断降级
本内容介绍了微服务中熔断降级的实现原理及Sentinel的底层机制。通过OpenFeign集成Sentinel,利用断路器统计异常和慢请求比例,触发熔断并降级,提升系统稳定性。还讲解了Sentinel使用的限流算法,如滑动窗口、令牌桶和漏桶算法,以应对不同场景下的流量控制需求。
|
4月前
|
存储 关系型数据库 MySQL
杂项9
行锁在数据库中用于并发控制,当更新操作能通过索引精确定位到具体行时生效,如 MySQL InnoDB。若未使用索引,可能升级为表锁,影响并发性能。更新操作优先使用行锁以保证数据一致性和高效并发。
|
4月前
|
存储 运维 安全
全面掌握 Consul:服务注册发现、健康检查、跨数据中心一网打尽
Consul 是一款广泛应用于微服务架构中的服务网格解决方案,具备服务注册与发现、健康检查、KV 存储、安全通信及多数据中心支持等核心功能,帮助开发者构建高效、稳定、高可用的分布式系统。
437 0
全面掌握 Consul:服务注册发现、健康检查、跨数据中心一网打尽
|
4月前
|
负载均衡 Java 应用服务中间件
杂项10
Spring Cloud Alibaba 与 Spring Cloud 均基于 Spring Boot 构建微服务,遵循相同规范且组件可协同使用。区别在于,Spring Cloud Alibaba 使用 Nacos 实现服务发现与配置管理,推荐 Sentinel 作为断路器,并支持 Dubbo 与 Feign 远程调用。Nginx 可通过配置 upstream 实现负载均衡,作为反向代理,其“反向”体现在外网通过 Nginx 访问内部服务器。
|
4月前
|
存储 NoSQL 算法
Redis的集群架构与使用经验
本文介绍了Redis的集群架构与使用经验,包括主从复制、哨兵集群及Cluster分片集群的应用场景与实现原理。内容涵盖Redis主从同步机制、数据分片存储方式、事务支持及与Memcached的区别,并讨论了Redis内存用尽时的处理策略。适用于了解Redis高可用与性能优化方案。