jvm

JVM垃圾回收

时间秒杀一切 提交于 2020-03-07 11:16:17
一.简介 最近又复习下jvm相关内容,理解下思想,吸收下前辈经验,本文jdk 1.7/1.8 二.引用计数法与可达性分析 垃圾回收,便是将已经分配出去的的,但却不再使用的内存回收回来,以便能够再次分配。在Java虚拟机的语境下,垃圾指的是死亡对象所占据的堆空间。这里便涉及了一个关键问题:如何辨别一个对象死亡。 2.1 引用计数法 给个对象添加引用计数器,每当有一个地方引用它,计数器值就加1;当引用失效时,计数器值就减一;任何时刻计数器为0的对象就是不再被使用。 引用计数法有个重大的漏洞,无法处理循环引用的对象。 public class ReferenceCountingGC { public Object instance = null; private static final int _1MB = 1024*1024; //占内存 private byte[] bigSize = new byte[2 *_1MB]; public static void testGC(){ ReferenceCountingGC objA = new ReferenceCountingGC(); ReferenceCountingGC objB = new ReferenceCountingGC(); objA.instance = objB; objB.instance = objA;

Java开发入门

你说的曾经没有我的故事 提交于 2020-03-07 07:52:33
Java概述 JVM Java虚拟机(JVM Java Virtual Machine) JVM来负责Java程序在该系统中的运行。 JRE与JDK JRE(Java Runtime Environment Java运行环境) 包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。 JDK(Java Development Kit Java开发工具包) JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE。所以安装了JDK,就不用在单独安装JRE了。 其中的开发工具:编译工具(javac.exe) 打包工具(jar.exe)等。 系统环境变量 path环境变量 编译java文件的外部指令javac,由于javac指令只能在JDK安装目录下的bin目录下执行,因此程序只能写入bin目录。程序开发过程中,不能将源代码写入JDK的安装目录,因此需要将源程序保存到任意位置的指定目录(英文目录),所以需要使javac指令在任意目录下可以运行。(用户变量与系统变量均可,最好系统变量) 创建新的变量名称:JAVA_HOME,为JAVA_HOME 添加变量值:JDK安装目录下的bin目录 将path环境变量中JDK目录修改%JAVA_HOME%\bin

jvm学习006 jvm内存结构分配

穿精又带淫゛_ 提交于 2020-03-07 06:13:10
主要内容如下: JVM启动流程 JVM基本结构 内存模型 编译和解释运行的概念 一、JVM启动流程: JVM启动时,是由java命令/javaw命令来启动的。 二、JVM基本结构: JVM基本结构图: 《深入理解Java虚拟机(第二版)》中的描述是下面这个样子的: Java中的内存分配: Java程序在运行时,需要在内存中的分配空间。 为了提高运算效率,就对数据进行了不同空间的划分 ,因为每一片区域都有特定的处理数据方式和内存管理方式。 具体划分为如下 5个内存空间 :(非常重要) 栈 :存放 局部变量 堆 :存放所有 new出来的东西 方法区:被虚拟机加载的类信息、常量、静态常量等。 程序计数器(和系统相关) 本地方法栈 1、程序计数器: 每个线程拥有一个PC寄存器 在线程创建时创建 指向下一条指令的地址 执行本地方法时,PC的值为undefined 2、方法区: 保存装载的类信息   类型的常量池   字段,方法信息   方法字节码 通常和永久区(Perm)关联在一起 3、堆内存: 和程序开发密切相关 应用系统对象都保存在Java堆中 所有线程共享Java堆 对分代GC来说,堆也是分代的 GC管理的主要区域 现在的GC基本都采用分代收集算法,如果是分代的,那么堆也是分代的。如果堆是分代的,那堆空间应该是下面这个样子: 上图是堆的基本结构,在之后的文章中再进行详解。 4、栈内存:

JVM学习笔记

岁酱吖の 提交于 2020-03-07 04:57:10
JVM学习笔记 JAVA内存模型 垃圾回收(可达性分析算法) JVM调优 JAVA内存模型 Java虚拟机由类加载系统、运行时数据区(堆,栈,本地方法栈,方法区,程序计数器)、字节码执行引擎组成。 堆:用于存程序中创建的对象。 栈(FILO):局部变量的存放地址。 本地方法栈:本地方法(native修饰的方法,如:Thread类中的start方法)的内存区域。 方法区:用于存放类信息、静态变量、静态常量。 程序技数器:用于记录CPU切换后程序的执行位置。 垃圾回收(可达性分析算法) 就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。 可以作为GC Root 引用点的是: JavaStack中的引用的对象。 方法区中静态引用指向的对象。 方法区中常量引用指向的对象。 Native方法中JNI引用的对象。 JVM调优 JVM调优的重点就是要减少FullGC 因为FullGcC会产生STW(stop the world)停止正在运行的线程去回收整个内存区域,会导致应用卡顿。 调优:对于频繁产生垃圾对象的系统,应该估算出产生垃圾对象的所占空间的大小

JVM内存结构

空扰寡人 提交于 2020-03-06 16:22:27
java程序运行 java源文件,通过编译器,能够生产响应的.class文件,也就是字节码文件,而字节码文件通过java虚拟机中的解释器,编译成特定机器上的机器码 过程 : java源文件 ----> 编译器 ---->字节码文件 ----->JVM ----> 机器码 每一个平台的解释器是不同的,但是实现的虚拟机是相同的,这就是java能够跨平台的原因,当一个程序开始运行,这是虚拟机就开始实例化了,多个程序启动就会存在多个虚拟机实例。程序退出或者关闭,则虚拟机实例消亡,多个虚拟机实例之间数据不能共享 JVM内存区域 程序计数器(线程私有) 记录的是虚拟机字节码指令的地址,每个线程都有一个独立的程序计数器。 这个内存区域是唯一一个在虚拟机中没有任何OutOfMemoryError情况的区域 虚拟机栈(线程私有) 每一个方法在执行的时候都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接、方法返回值等信息。方法被调用,栈帧入栈,方法执行完毕,栈帧出栈。 栈帧 :随方法调用而创建,随方法结束而销毁,无论方法时正常完成还是异常抛出都算方法结束 操作数栈 :主要是方法中计算的部分,会进入操作数栈,计算的数值出栈,计算完成之后再将结果返回栈中。 本地方法区(线程私有) 区别于细腻基站为执行java方法服务,而本地方法区则为Native方法服务。 native方法

类加载机制学习

给你一囗甜甜゛ 提交于 2020-03-06 10:15:50
简单讲下JVM中的类加载过程 JVM中的类加载和卸载的时机? 如何理解JVM中不同类加载器的概念和作用? 简单讲下JVM中的双亲委派模型? 什么情况下会破坏双亲委派模型?为什么?可否举个例子? Tomcat中的类加载机制有了解吗?为什么这么设计? 实际开发中有遇到哪些类加载器相关的问题?你又是如何解决的? JVM之上的弱类型语言例如Groovy是如何实现?简单讲下动态类加载机制? 类的加载和卸载 JVM是虚拟机的一种,它的指令集语言是字节码,字节码构成的文件是class文件。平常我们写的Java文件,需要编译为class文件才能交给JVM运行。可以这么说:C语言代码——>二进制文件——>计算机硬件,就相当于Java代码——>字节码文件——>JVM。JVM将指定的class文件读取到内存里,并运行该class文件里的Java程序的过程,就称之为类的加载;反之,将某个class文件的运行时数据从JVM中移除的过程,就称之为类的卸载。 class文件的运行时数据就是C++对象,也称为kclass对象,这些运行时数据在JDK7之前是放在永久代(PermGen),JDK8之后则放在元空间(Metaspace)。 类的生命周期 Java类从被虚拟机加载开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析

JVM学习:如何使用visualGC调优Eclipse启动过程。

旧街凉风 提交于 2020-03-06 00:19:29
转载自品略网: http://www.pinlue.com/article/2020/03/0422/199981849836.html 最近在学习JVM,了解了一些关于JVM的内存分配和垃圾回收的知识,其中有有一个实战是优化Eclipse的启动,从类加载时间、JIT编译时间、垃圾收集时间三个方面做了优化,简单、综合性强,可以加深对JVM的理解,所以这里对其进行验证。 硬件和操作系统环境: Java版本(HotSpot虚拟机): Eclipse相关信息: 原始的启动配置: 最大永久代空间是256M,初始堆40M,最大512M 启动后的GC信息,使用jvisualvm工具查看: 使用eclipse插件来对eclipse启动计时。 优化类加载速度: 使用jstat -class ID查看类加载,原始情况如下: 考虑到不需要再加载的时候进行字节码验证,因此通过参数-Xverify:none禁止掉字节码验证过程。优化后的类加载时间变为,大概降低为原来的一半时间: 优化编译时间: 编译时间是指虚拟机的JIT(just in time compiler)编译器编译热点代码的耗时,虚拟机解释执行字节码速度慢,通过虚拟机内置的运行时编译器,将热点代码即时编译为本地代码,以提高运行速度。 -Xint参数禁止编译器运作,强制虚拟机对字节码采用纯解释方式执行。 当虚拟机运行在-client模式的时候

JVM老年代和新生代的比例

谁都会走 提交于 2020-03-05 23:33:42
Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。 这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。 堆的内存模型大致为: 从图中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。 (本人使用的是 JDK1.6,以下涉及的 JVM 默认值均以该版本为准。) 默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ) ,即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。 默认的,Edem : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的新生代空间大小,from =

JVM的内存区域划分以及垃圾回收机制详解

假如想象 提交于 2020-03-05 18:59:00
在我们写 Java 代码时,大部分情况下是不用关心你New的对象是否被释放掉,或者什么时候被释放掉。因为JVM中有垃圾自动回收机制。在之前的博客中我们聊过 Objective-C 中的 MRC (手动引用计数)以及 ARC (自动引用计数)的内存管理方式,下方会对其进行回顾。而目前的JVM的内存回收机制则不是使用的引用计数,而是主要使用的“复制式回收”和“自适应回收”。 当然除了上面是这两种算法外,还有其他是算法,下方也将会对其进行介绍。本篇博客,我们先简单聊一下 JVM的区域划分 ,然后在此基础上介绍一下JVM的垃圾回收机制。 一、JVM内存区域划分简述 当然本部分简单的聊一下JVM的内存区域的划分,为下方垃圾回收机制内容的展开进行铺垫。当然对JVM内存区域划分的内容网上有好多详细的内容,请自行Google。 根据JVM内存区域的划分,简单的画了下方的这个示意图。区域主要分为两大块,一块是 堆区(Heap) ,我们所New出的对象都会在堆区进行分配,在C语言中的malloc所分配的方法就是从Heap区获取的。而垃圾回收器主要是对堆区的内存进行回收的。 而另一部分则是 非堆区 ,非堆区主要包括用于编译和保存本地代码的“代码缓存区( Code Cache )”、保存JVM自己的静态数据的“永生代( Perm Gen )”、存放方法参数局部变量等引用以及记录方法调用顺序的

JVM源码分析之不可控的堆外内存

我怕爱的太早我们不能终老 提交于 2020-03-05 13:27:10
概述 之前写过篇文章,关于堆外内存的, JVM源码分析之堆外内存完全解读 ,里面重点讲了DirectByteBuffer的原理,但是今天碰到一个比较奇怪的问题,在设置了-XX:MaxDirectMemorySize=1G的前提下,然后统计所有DirectByteBuffer对象后面占用的内存达到了7G,远远超出阈值,这个问题很诡异,于是好好查了下原因,虽然最终发现是我们统计的问题,但是期间发现的其他一些问题还是值得分享一下的。 不得不提的DirectByteBuffer构造函数 打开DirectByteBuffer这个类,我们会发现有5个构造函数 DirectByteBuffer(int cap); DirectByteBuffer(long addr, int cap, Object ob); private DirectByteBuffer(long addr, int cap); protected DirectByteBuffer(int cap, long addr,FileDescriptor fd,Runnable unmapper); DirectByteBuffer(DirectBuffer db, int mark, int pos, int lim, int cap,int off) 我们从java层面创建DirectByteBuffer对象