JVM
摸鱼小能手tay
这个作者很懒,什么都没留下…
展开
-
Java 自带性能监控工具:监视和管理控制台 jconsole 的使用
1. 前言Java 自带性能监控工具:监视和管理控制台 jconsole,它可以提供 Java 某个进程的内存、线程、类加载、jvm 概要以及 MBean 等的实时信息。2. JVM 一些参数在启动 jconsole 之前我们先来回顾一下 JVM 的一些主要参数:-Xms 初始/最小堆内存大小-Xmx 最大堆内存大小-Xmn 年轻代大小-XX:NewSize 年轻代大小-XX:MaxNewSize 年轻代最大值-XX:NewRatio 年老代与年轻代比值-XX:MaxPermSize 持转载 2020-09-25 10:43:40 · 561 阅读 · 0 评论 -
volatile型变量的特殊规则
关键字volatile可以说是Java虚拟机提供的最轻量级的同步机制。当一个变量被volatile修饰后,①可以保证该变量对所有线程的可见性。(当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的)如果是普通变量,它的值在线程间传递时均需要通过主内存来完成。比如, 线程A修改一个普通变量的值,然后向主内存进行回写,另外一条线程B在线程A回写完成了之后再对主内存进行读取操作,新变量值才会对线程B可见。Java里面的运算操作符并非原子操作, 这导致volatile变量的运算在并发下是不安全的原创 2020-08-06 10:28:17 · 195 阅读 · 0 评论 -
内存间的交互
即变量如何从主内存拷贝到工作内存、从工作内存同步回主内存。Java内存模型中定义了8种操作来完成:1、lock(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态。2、unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。3、read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到工作内存中,以便随后的load动作使用。4、load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的原创 2020-08-03 14:23:36 · 420 阅读 · 1 评论 -
Java内存模型
Java内存模型:主要目的是定义程序中各种变量的访问规则。即关注在Java虚拟机中把变量值存储到内存和从内存中取出变量值这样的底层细节。(这里的变量包括实例字段、静态字段、构成数组对象的元素;因为局部变量与方法参数是线程私有的,不会被共享,就不会存在竞争问题)Java内存模型规定了所有变量都存储在主内存。每条线程都有自己的工作内存,线程的工作内存中保存了被该线程使用的变量的主内存副本,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存数据。不同的线程之间也无法直接访问对方工作内存中的变量,线原创 2020-08-03 14:20:14 · 110 阅读 · 0 评论 -
类加载器和双亲委派模型
类加载器:通过一个类的全限定名来获取描述该类的二进制字节流。(Java虚拟机外部实现)对于任意一个类,都是由加载它的类加载器和这个类本身共同确立在Java虚拟机中的唯一性。同一个class文件,如果一个由虚拟机应用程序类加载器加载(虚拟机本身的类加载器),一个由自定义类加载器加载,那么它们将是2个独立的类。启动类加载器(Bootstrap Class Loader):负责加载存放于<JAVA_HOME>\lib目录下,或者被-Xbootclasspath参数所指定的路径中存放的类库加载到原创 2020-07-26 00:06:34 · 119 阅读 · 0 评论 -
类加载的过程
1、加载:①通过一个类的全限定名来获取定义此类的二进制字节流。②将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。③在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。2、验证:是连接阶段的第一步,这一阶段的目的是确保Class文件的字节流中包含的信息符合《Java虚 拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。包括文件格式验证、元数据验证、字节码验证和符号引用验证。(避免遭受恶意代码的攻击)3、准原创 2020-07-19 21:33:32 · 129 阅读 · 0 评论 -
虚拟机类加载机制
类加载机制:Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析初始化,最终形成可以被虚拟机直接使用的Java类型的过程。一个类从被加载到虚拟机内存再到卸载出内存,它的整个生命周期将会经历加载(Loading)、验证(Verfication)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading) 七个阶段;其中验证、准备、解析三个部分统称为连接。*类加载的过程必须按加载验证准备初原创 2020-07-19 21:29:26 · 108 阅读 · 0 评论 -
Class类文件结构
任何一个Class文件都对应着唯一的一个类或接口的定义信息。Class文件是一组以8个字节为基础的二进制流,各个数据项严格按照顺序紧凑排列在文件中,中间没有任何分隔符。这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。当遇到需要占用8个字节以上空间的数据项时,则会按照高位在前[2]的方式分割成若干个8个字节进行存储。Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构只有2种数据类型:无符号数和表无符号数:数属于基本的数据类型,以u1、u2、u4、u原创 2020-07-18 18:05:24 · 107 阅读 · 0 评论 -
垃圾收集器日志
JDK9之后,HotSpot所有功能的日志都收归到了“-Xlog”参数上-Xlog[:[selector][:[output][:[decorators][:output-options]]]]selector:选择器,由标签Tag和日志级别Level共同组成(标签可以理解为迅即某个功能模块的名字) 日志级别从低到高,Trace,Debug,Info,Warning,Error,Off六种级别 decorator修饰器可以要求每行日志输出都附加上额外的内容,支持附加在日志上的信息包括:原创 2020-07-14 18:19:42 · 335 阅读 · 0 评论 -
经典垃圾收集器
**1、Serial收集器:**最基础的垃圾收集器,单线程工作的收集器。它在进行垃圾收集的时候,必须暂停其他所有工作线程,直到它收集结束。它是HotSpot虚拟机运行在客户端模式下的默认新生代收集器,因为相对来说它简单高效,额外内存消耗最小**2、ParNew收集器:**支持多线程,只有它能与CMS收集器配合工作,是HotSpot虚拟机中第一款真正意义上支持并发的垃圾收集器,它首次实现了让垃圾收集线程与用户线程(基本上)同时工作。随着G1的出现,自JDK9开始,基本退出历史舞台3、Parallel Sc原创 2020-07-10 17:17:59 · 129 阅读 · 0 评论 -
垃圾收集算法
1.新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。2.老年代收集(Major GC/Old GD):指目标只是老年代的垃圾收集。3.混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。4.整堆收集(Full GC):整个Java堆和方法区的垃圾收集。标记清除算法:分为“标记”和“清除”两个阶段,首先标记出所有需要回收的对象,在标记完成之后,统一回收掉所有被标记的对象。缺点:①执行效率不稳定。对象数量越多执行效率越慢,需要大量标记和清除的原创 2020-07-08 16:05:36 · 131 阅读 · 0 评论 -
Java引用类型
判断对象是否存活和引用离不开关系,对于一些对象,我们希望在内存空间还足够时它能保留在内存里,当内存空间在进行垃圾收集之后仍然非常紧张,就抛弃这些对象。所以在JDK1.2之后,Java对引用的概念进行扩充。强引用:在程序代码中普遍存在的引用赋值,如Object obj = new Object()这种引用关系;只要强引用的关系还在,垃圾收集器就永远不会回收掉被引用的对象。软引用:被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围中进行二次回收,如果回收之后还没有足够的内存,才会原创 2020-07-08 13:48:14 · 102 阅读 · 0 评论 -
如何判断对象可被回收
1、引用计数法在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。它虽然占用了一些额外的内存空间来进行计数,但是它的效率高。但它也有很多例外的情况需要考虑,比如单纯的引用计数很难解决对象之间相互循环引用的问题。2、可达性分析当前主流的程序语言的内存资管子管理系统,都是采用的可达性分析算法来判断对象是否存活的。从GC Roots开始,根据引用关系向下搜索,(搜索过程所走过的路径称为“引用链”),如果某个对象到G原创 2020-07-08 11:21:32 · 251 阅读 · 0 评论 -
Java堆内存溢出异常测试(OutOfMemoryError异常实战)
Java堆用于存储对象实例,我们不断地创建对象,要保证GC Roots到对象间有可达路径才能避免垃圾回收机制清除这些对象。但是随着对象数量的增加,总容量触及最大堆的容量限制后就会产生内存溢出异常。我们限制Java堆大小为20MB,将堆的最小值-Xms与最大值-Xmx设置为一样来让堆不可扩展。通过参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机 在出现内存溢出异常的时候Dump出当前的内存堆转储快照以便进行事后分析public class HeapOOM { sta原创 2020-07-07 11:03:43 · 721 阅读 · 0 评论 -
对象的访问方式
①句柄用句柄访问,Java堆中会划分出一块作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象实例数据与类型数据各自具体的地址信息。(使用句柄来访问的最大好处就是reference中存储的是稳定句柄地 址,在对象被移动时只会改变句柄中的实例数据指针,而 reference本身不需要被修改。)②直接指针使用直接指针访问,Java堆中的对象的内存布局就必须考虑如何放置访问类型数据相关的信息,reference中存储的直接就是对象地址。(使用直接指针来访问最大的好处就是速度更快,它节原创 2020-07-06 15:25:11 · 197 阅读 · 0 评论 -
对象的内存布局
分为对象头、实例数据、对齐填充三部分。1、对象头包括两类信息。一类用于存储对象自身的运行时数据(如哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等);另一类是类型指针,即对象指向它的类型元数据的指针,Java虚拟机通过这个指针来确定该对象是哪个类的实例。2、实例数据:在程序代码中定义的各种类型的字段内容。这部分的存储顺序会受到虚拟机分配策略参数和字段在Java源码中定义的顺序影响。3、对齐填充:这部分不是必然存在的,仅仅起着占位符的作用。...原创 2020-07-06 13:51:42 · 84 阅读 · 0 评论 -
对象的创建过程
Java对象的创建通常用new关键字,当Java虚拟机遇到一条new字节码指令时,首先会去检查这个对象是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已加载解析初始化,如果没有,则会执行类加载过程。①类加载之后,虚拟机会为新生对象分配内存。对象所需的内存大小再类加载完可以确定。②内存分配完之后,虚拟机需将分配到的内存空间初始化为零值(保证实例字段在不赋初始值时可以直接使用)③虚拟机对对象头进行设置。...原创 2020-07-06 11:27:59 · 120 阅读 · 0 评论 -
运行时数据区域详解
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。1.程序计数器:可以看作是当前线程所执行的字节码行号指示器。(线程私有)由于Java虚拟机的多线程是通过线程轮流切换、分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器都会执行一条线程中的指令。为了保证线程切换后能回到原来的正确位置,每条线程都需要有有一个独立的程序计数器;各条程序计数器独立存储互不影响,这类内存区域称之为“线程私有”的内存。如果线程正在执行的是Java方法,那么这个计数器记录的是正原创 2020-07-05 20:22:39 · 319 阅读 · 0 评论 -
为什么要了解Java虚拟机
Java虚拟机在千差万别的物理机上面建立了统一的运行平台,实现了在任意一台Java虚拟机上编译的程序都能够在其他Java虚拟机上正常运行。所以使Java应用的开发比C/C++应用开发更高效快捷。虚拟机会自己完成对硬件平台的兼容及对内存等资源的管理工作。 当一段程序被10个人使用时完全正常,但是当1w个人同时使用的时候,需要更高性能的物理硬件,但在绝大多是情况下,提升硬件性能无法等比例提升程序的运行性能和并发能力,甚至没有任何改善。这里除了Java虚拟机为了达到所有硬件提供一致的虚拟平台而牺牲了一些硬件相.原创 2020-07-04 17:53:30 · 154 阅读 · 0 评论