java程序员必须知道的内存知识-应用层

简介: 1.volatile可见性,使用volatile修饰的变量可以立刻被其它线程读取到,经常会被用到多线程同步的关键变量上,像aqs的state。因为CPU在访问主存需要大约十几个时钟周期,为了提高cpu的效率便有了高速缓存,当数据被加载到高速缓存时,其它核并不能第一时间看到。内存屏障,最常见的就是双检锁了,我们简单的new对象在虚拟机内部其实需要很多操作,虚拟机为了提高性能,会对我们代码进行重排,使用volatile可以保证变量在被编译时的顺序性。

1.volatile


可见性,使用volatile修饰的变量可以立刻被其它线程读取到,经常会被用到多线程同步的关键变量上,像aqs的state。

image.png

因为CPU在访问主存需要大约十几个时钟周期,为了提高cpu的效率便有了高速缓存,当数据被加载到高速缓存时,其它核并不能第一时间看到。内存屏障,最常见的就是双检锁了,我们简单的new对象在虚拟机内部其实需要很多操作,虚拟机为了提高性能,会对我们代码进行重排,使用volatile可以保证变量在被编译时的顺序性。


image.png


volatile、synchronized、final都会影响虚拟机的指令重排,会通过指令集中的loadload、storestore、loadstore、storeload四个内存屏障实现。总结来说,volatile的作用有3个,编译重排(虚拟机优化重排)、指令重排(cpu指令重排)、内存重排(高速缓存脏读)


2.缓存行


缓存行是为了解决cpu访问主存时间长的问题,之前文章有过介绍。https://segmentfault.com/a/11...https://segmentfault.com/a/11...

缓存行友好

因为缓存行会存储多份数据,所以有了缓存行一致性协议,但一致性协议有一定成本,如果缓存行被共享,又频繁修改,会导致性能下降。解决办法也很简单,就是让一个缓存行只有一条数据,保证数据独享。java8提供了jdk.internal.vm.annotation.Contended注解,在类上加注解后,虚拟机会自动做缓存行填充。

缓存行抖动

因为缓存行大小有限,所以缓存行只能缓存部分数据,因为缓存行采用映射的方式选择缓存的数据,如下图,如果ABCD四个数据都映射到上面的一个行里,当我们要访问A时,要把A加载进来,这时我们要访问B,要把缓存行清空,再加载B,这时如果还需要访问A,又得把B清掉,加载A,这就是缓存行抖动。

image.png


这是一个常见的例子,数组x和数组y同时映射到一个缓存行,当访问x[i]时,要加载x到缓存行,访问y[i]时又需要把y加载到缓存行,常见的解决办法也比较简单,就是扩充数组大小,让x和y无法映射到一个缓存行。


image.png


3.内存池


堆内存由jvm替我们申请和回收,但是垃圾回收也是我们系统的瓶颈之一,所以有些时候为了提高性能或者其他原因,我们也会使用堆外内存,例如netty,netty的堆外内存池使用的就是类似slab的机制实现的,如果有兴趣可以看看源码,这里就不细说了。


4.java引用


强引用

强引用就是我们平时使用的Object a = new Object()。如果一个对象具有强引用,那垃圾回收器就不会回收这个new Object()

软引用

如果一个对象只有软引用,在内存充足时垃圾回收器就不会回收它;如果内存空间不足了,就会回收软引用应用的对象。软引用的回收会根据上次gc剩余内存,软引用上次访问的时间动态调整,就是上次访问的时间越久,上次gc剩余内存越少,越容易被回收。

弱引用

如果一个对象只有弱引用,只要触发gc就会被回收(包括年轻代gc)。

虚引用

虚引用的get方法会直接返回null,虚引用的作用主要是对象在被回收时可以通过虚引用通知到程序,对象被回收了。





image.pngimage.pngimage.pngimage.pngimage.png

相关文章
|
2月前
|
安全 Java 应用服务中间件
Spring Boot + Java 21:内存减少 60%,启动速度提高 30% — 零代码
通过调整三个JVM和Spring Boot配置开关,无需重写代码即可显著优化Java应用性能:内存减少60%,启动速度提升30%。适用于所有在JVM上运行API的生产团队,低成本实现高效能。
254 3
|
3月前
|
存储 缓存 Java
Java数组全解析:一维、多维与内存模型
本文深入解析Java数组的内存布局与操作技巧,涵盖一维及多维数组的声明、初始化、内存模型,以及数组常见陷阱和性能优化。通过图文结合的方式帮助开发者彻底理解数组本质,并提供Arrays工具类的实用方法与面试高频问题解析,助你掌握数组核心知识,避免常见错误。
|
1月前
|
Java 大数据 Go
从混沌到秩序:Java共享内存模型如何通过显式约束驯服并发?
并发编程旨在混乱中建立秩序。本文对比Java共享内存模型与Golang消息传递模型,剖析显式同步与隐式因果的哲学差异,揭示happens-before等机制如何保障内存可见性与数据一致性,展现两大范式的深层分野。(238字)
59 4
|
6月前
|
人工智能 Kubernetes Java
回归开源,两位 Java 和 Go 程序员分享的开源贡献指引
Higress是一个基于Istio和Envoy的云原生API网关,支持AI功能扩展。它通过Go/Rust/JS编写的Wasm插件提供可扩展架构,并包含Node和Java的console模块。Higress起源于阿里巴巴,解决了Tengine配置重载及gRPC/Dubbo负载均衡问题,现已成为阿里云API网关的基础。本文介绍Higress的基本架构、功能(如AI网关、API管理、Ingress流量网关等)、部署方式以及如何参与开源贡献。此外,还提供了有效的开源贡献指南和社区交流信息。
618 33
|
1月前
|
存储 缓存 Java
【深入浅出】揭秘Java内存模型(JMM):并发编程的基石
本文深入解析Java内存模型(JMM),揭示synchronized与volatile的底层原理,剖析主内存与工作内存、可见性、有序性等核心概念,助你理解并发编程三大难题及Happens-Before、内存屏障等解决方案,掌握多线程编程基石。
|
2月前
|
缓存 监控 Kubernetes
Java虚拟机内存溢出(Java Heap Space)问题处理方案
综上所述, 解决Java Heap Space溢出需从多角度综合施策; 包括但不限于配置调整、代码审查与优化以及系统设计层面改进; 同样也不能忽视运行期监控与预警设置之重要性; 及早发现潜在风险点并采取相应补救手段至关重要.
492 17
|
3月前
|
监控 Kubernetes Java
最新技术栈驱动的 Java 绿色计算与性能优化实操指南涵盖内存优化与能效提升实战技巧
本文介绍了基于Java 24+技术栈的绿色计算与性能优化实操指南。主要内容包括:1)JVM调优,如分代ZGC配置和结构化并发优化;2)代码级优化,包括向量API加速数据处理和零拷贝I/O;3)容器化环境优化,如K8s资源匹配和节能模式配置;4)监控分析工具使用。通过实践表明,这些优化能显著提升性能(响应时间降低40-60%)同时降低资源消耗(内存减少30-50%,CPU降低20-40%)和能耗(服务器功耗减少15-35%)。建议采用渐进式优化策略。
191 1
|
3月前
|
存储 监控 算法
Java垃圾回收机制(GC)与内存模型
本文主要讲述JVM的内存模型和基本调优机制。
|
4月前
|
SQL 缓存 安全
深度理解 Java 内存模型:从并发基石到实践应用
本文深入解析 Java 内存模型(JMM),涵盖其在并发编程中的核心作用与实践应用。内容包括 JMM 解决的可见性、原子性和有序性问题,线程与内存的交互机制,volatile、synchronized 和 happens-before 等关键机制的使用,以及在单例模式、线程通信等场景中的实战案例。同时,还介绍了常见并发 Bug 的排查与解决方案,帮助开发者写出高效、线程安全的 Java 程序。
227 0