
JVM学习篇
穷水叮咚
这个作者很懒,什么都没留下…
展开
-
(一)初识JAVA栈
先看图: 这是一张比较官方的虚拟机模型图,今天讲的就是虚线框中栈的部分。 栈是我们最常用的内存区域。它主要用来存放基本类型变量,局部变量以及对象的引用。例如:User user = new User();这里的user就是对象的引用也可以理解为地址,指引着虚拟机要去哪里找user这个对象。 他们的基本关系如图: 由图可知,当我们将一个对象作为方法的参数时,我们在方法中改变对象的值,...转载 2018-05-25 11:44:17 · 184 阅读 · 0 评论 -
(十二)JAVA G1收集器
先讲讲G1收集器的特点,他也是个多线程的收集器,能够充分利用多个CPU进行工作,收集方式也与CMS收集器类似,因此不会有太久的停顿。 虽然回收的范围是整个堆,但还是有分代回收的回收方式。在年轻代依然采用复制算法;年老代也同样采用“标记-清除-整理”算法。但是,新生代与老年代在堆内存中的布局就和以往的收集器有着很大的区别:G1将整个堆分成了一个个大小相等的独立区域,叫做region。其中依然保存...转载 2018-05-28 14:13:58 · 823 阅读 · 0 评论 -
(十三)JAVA 可视化分析工具
我们今天要讲解的工具位于JDK目录的bin目录下,大家可以发现该目录下有很多可执行文件,这里都是JDK为我们提供用于分析内存的一些工具。我们重点看看jconsole.exe,JAVA监视与管理控制台。 先运行以下程序: 再双击运行可视化工具,这里会让你选择要监控的程序,我们选择刚刚运行的程序。结果如图: 该页面只是一个概览页面,我们可以点进去上方导航栏的内存页,进去后我们可查看内存中各...转载 2018-05-28 14:14:09 · 2600 阅读 · 0 评论 -
(十四)JAVA 类加载机制
从本篇博文开始,我们就进入虚拟机类加载机制的学习了。那么什么是类加载呢?当我们写完一个Java类的时候,并不是直接就可以运行的,它还要编译成.class(字节码)文件,再由虚拟机解释给当前的操作系统去执行。这些过程都是我们看不见的,我们能看见的也就是一个.class文件。既然虚拟机要解释这些.class文件给当前的操作系统听,那么他怎么获得这些.class文件呢?虚拟机获得这些.class文件的过...转载 2018-05-28 15:38:29 · 137 阅读 · 0 评论 -
(十五)JAVA 类加载器
今天我们将类加载机制5个阶段中的第一个阶段,加载,又叫做装载。为了便于阅读,以下都叫做装载。 装载的第一步就是要获得二进制的字节流,它可以从读.class文件获得,也可以从网络中接收别人发送的字节流。反正只要符合虚拟机规定的字节流格式都可以进入这个阶段。 有了字节流之后,要进行装载还需要一个工具,那就是加载器了。加载器既可以使用系统提供的引导类加载器,也可以使用用户自己定义加载器,只需要继...转载 2018-05-28 16:23:31 · 158 阅读 · 0 评论 -
(十六)JAVA 双亲委派模型
在上一篇博文中,我们知道了如何获得二进制的字节流,并根据获得的字节流去装载一个类。同时也了解到类加载器的存在,每个加载器对应着不同的加载目录,相互配合着,从而使整个加载过程稳定而安全。 那么他们是如何配合的呢?如果我自己写一个类,名字叫做String可以吗? 首先我们来看一张图: 图中除了最底下的那个加载器是我们没有讲到的,其余的都有说到过。其实底下那个就是我们自己实现的类加载器,用...转载 2018-05-28 16:27:40 · 171 阅读 · 0 评论 -
java既然存在gc线程,为什么还存在内存泄漏?
1.既然 Java 的垃圾回收机制能够自动的回收内存,怎么还会出现内存泄漏的情况呢?这个问题,我们需要知道 GC 在什么时候回收内存对象,什么样的内存对象会被 GC 认为是“不再使用”的。Java中对内存对象的访问,使用的是引用的方式。在 Java 代码中我们维护一个内存对象的引用变量,通过这个引用变量的值,我们可以访问到对应的内存地址中的内存对象空间。在 Java 程序中,这个引用变量本身既可以...转载 2018-07-04 09:55:24 · 1449 阅读 · 0 评论 -
java dump文件怎么生成和分析-JMAP用法
jmap是java自带的工具1. 查看整个JVM内存状态 jmap -heap [pid]2. 查看JVM堆中对象详细占用情况jmap -histo [pid]3. 导出整个JVM 中内存信息,可以利用其它工具打开dump文件分析,例如jdk自带的visualvm工具jmap -dump:file=文件名.dump [pid] 转载自:https://blog....转载 2018-08-18 23:45:15 · 4304 阅读 · 0 评论 -
java类的加载机制深入理解
java类的加载机制 1、什么是类的加载类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数...转载 2018-10-09 15:02:04 · 159 阅读 · 0 评论 -
(十一)JAVA 年老代收集器
本篇博文我们要讲的就是关于老年代的一些收集器。老年代存活的一般是大对象以及生命很顽强的对象,因此新生代的复制算法很明显不能适应该区域的特性,所以老年代采用的是“标记-清除-整理”算法(以前的博文有详细讨论过)。Serila Old收集器:该收集器是Serial收集器的老年代版,同样是一个单线程的收集器,优劣势和Serial收集器一样,这里就不多说了。Parallel Old收集器:在我们之前文章的...转载 2018-05-28 13:58:03 · 159 阅读 · 0 评论 -
(十)JAVA 年轻代收集器
STW即GC时候的停顿时间,他会暂停我们程序中的所有线程。如果STW所用的时间长而且次数多的话,那么我们整个系统稳定性以及可用性将大大降低。 因此我们在必要的时候需要对虚拟机进行调优,调优的主要目标之一就是降低STW的时间,也就是减少Full GC的次数。那么这里我们从调优的角度来分析各个收集器的优势与不足。 首先从作用于年轻代的收集器开始(采用复制的收集算法):Serial收集器:一个单...转载 2018-05-25 15:48:24 · 304 阅读 · 0 评论 -
(二)JAVA堆
在博文《JVM进阶(一)——初识JAVA栈》中我们说到了栈,他在内存中是连续的空间;保存一个个的栈帧,对应一次次方法的调用;还讲到了他是保存对象的引用,那么对象存在哪里呢?我们来看看昨天的一张图: 对象就存在图中的内存区域,在JVM中,那片区域叫做堆! 由图中可以看到堆的存储结构和栈是不同的,堆在内存中并不是一块连续的区域,他是分散的(物理上是分散,但逻辑上是连续的,大家好好体会一下);...转载 2018-05-25 11:51:25 · 232 阅读 · 0 评论 -
(三)内存分配与回收策略
虚拟机中的堆,他是整个内存模型中占用最大的一部分,而且不是连续的。当有需要分配内存的时候,一般有两个方法分配,指针碰撞和空闲列表。该部分的内存回收是由虚拟机的垃圾收集器GC进行管理的。 刚刚粗略的回忆了上一博文所讲的内容,而这一章我们的重点还在堆上面。之前有简单的提到过新生代和老年代,今天就给大家好好梳理下这部分。 堆是存放对象以及数组的区域,但不是胡乱的有空间就分配的内存。堆在内存中分为...转载 2018-05-25 11:53:24 · 204 阅读 · 0 评论 -
(四)java堆中的年轻代
1.为什么会有年轻代我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描。而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存“朝生夕死”对象的区域进行回收,这样就会腾出很大...转载 2018-05-25 11:56:38 · 1583 阅读 · 0 评论 -
(五)利用MAT排查堆溢出
堆已经讲得差不多啦,这章我们以一个例子来说说如何设置以及当发生堆溢出的时候怎么排查问题。先看一小段代码: 代码中使用了一个无限循环来为list添加对象,如果采用默认的堆大小的话可能要等待好久才能出现堆溢出的错误,因此我们要将其设置小一点: -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError,elipse中的设置方法我们在第一章讲过了,这里不多说...转载 2018-05-25 13:24:30 · 334 阅读 · 0 评论 -
(六)java堆中年老代之GC标记
前言 堆分为年轻代和年老代。永久代是非堆内存,它又叫做方法区(一般的说法),主要存储已被加载的类信息、常量、静态变量。而该区域在java8已被删除,取而代之的是元空间,我会在后面的章节细讲。什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理。 至于怎么标记,一般有两种方法:引用计数和可达性分析。 引用计数实现起来比较简单,就是给对象添加...转载 2018-05-25 13:39:25 · 264 阅读 · 0 评论 -
(七)JVM之二次标记
上一章我们讲到了标记,但是不是被标记了就肯定会被回收呢?不知道小伙伴们记不记得Object类有一个finalize()方法,所有类都继承了Object类,因此也默认实现了这个方法。 这个方法的用途就是:在该对象被回收之前,该对象的finalize()方法会被调用。这里的回收之前指的就是被标记之后,问题就出在这里,有没有一种情况就是原本一个对象开始不在上一章所讲的“关系网”(引用链)中,但是当开...转载 2018-05-25 14:30:42 · 585 阅读 · 0 评论 -
(八)从GC日志分析堆内存
在前面的文章中,我们只设置了整个堆的内存大小。但是我们知道,堆又分为了新生代,年老代。他们之间的内存怎么分配呢?新生代又分为Eden和Survivor,他们的比例大小能改变吗?其实这些都是可控的,以前没有讲到是因为就算讲了也只是讲讲而已,看不到实质性的东西。因此这章我们通过分析GC日志来一步步讲解如何细化设置堆内存。 首先我们来了解几个相关的参数:-XX:+PrintGCDetails:用于告...转载 2018-05-25 14:42:57 · 597 阅读 · 0 评论 -
(九)Stop The World
小伙伴还记得上一篇中我们留下的一个问题吗?什么是停顿类型!经过前几章的学习,我们知道垃圾回收首先是要经过标记的。对象被标记后就会根据不同的区域采用不同的收集方法。看上去很完美的一件事情,其实并不然。 大家有没有想过一件事情,当虚拟机完成两次标记后,便确认了可以回收的对象。但是,垃圾回收并不会阻塞我们程序的线程,他是与当前程序并发执行的。所以问题就出在这里,当GC线程标记好了一个对象的时候,此时...转载 2018-05-25 15:15:06 · 173 阅读 · 0 评论 -
强引用,软引用,弱引用,虚引用
用了Java怎么长时间一直不知道原来Java还有四种引用类型,这个引用类型和我们平常说的可不一样。这里的引用类型不是指数据类型的一种,而是指Java中的引用所分的四种类型。他们代表了JVM回收内存的四种强度,分别如下。强引用:Java中的引用,有点像C++的指针。通过引用,可以对堆中的对象进行操作。在某函数中,当创建了一个对象,该对象被分配在堆中,通过这个对象的引用才能对这个对象进行操作。...转载 2019-05-12 18:03:26 · 138 阅读 · 0 评论