jvm

jvm关闭

。_饼干妹妹 提交于 2020-02-05 13:50:12
关闭方式 正常关闭 最后一个普通线程(非守护线程)结束 调用了System.exit 发送SIGINT信号(相当于不带参数的kill命令)或者键入Ctrl-C 强制关闭 调用Runtime.halt 发送SIGKILL信号(kill -9 命令) 关闭钩子(Shutdown Hook) 钩子配置方法 通过下面的设置方法可看到,关闭钩子实际为线程 Runtime . getRuntime ( ) . addShutdownHook ( new Thread ( ( ) - > { } ) ) ; 触发调用Hook线程流程 正常关闭中,JVM首先调用所有已注册的关闭钩子。JVM并不能保证关闭钩子的调用顺序。在关闭应用程序线程时,如果有线程仍然在运行,那么这些线程接下来将与关闭进程并发进行。 当所有的关闭钩子都执行结束时,如果runFinalizersOnExit为true,那么JVM将运行终结器,然后再停止。JVM并不会停止或中断任何在关闭时仍然运行的应用程序线程。当JVM最终结束时,这些线程将被强行结束。 如果关闭钩子或终结器没有执行完成,那么正常关闭进程挂起并且JVM必须被强行关闭。 –《Java并发编程实战》 上述是书里面的介绍,下面跟着源码对照整个流程: 添加钩子 Runtime: public void addShutdownHook ( Thread hook ) {

记一次内存溢出查找分析文档

我怕爱的太早我们不能终老 提交于 2020-02-05 09:26:22
内存溢出介绍。 内存溢出和内存泄漏的联系: 内存泄漏会最终导致内存溢出。 相同点:都会导致应用程序运行出现问题,性能下降或挂起。 不同点: 1 内存泄漏是导致内存溢出的原因之一,内存泄漏积累起来导致内存溢出。 2 内存泄漏可以通过完善代码来避免,内存溢出可以通过调整完善代码来避免,内存溢出可以通过调整配置来减少发生频率,但无法彻底避免。 内存溢出 内存溢出 (out of memory),是指程序在申请内存时,没有足够的内存空间供其使用,出现 out of memory ; 比如申请了一个integer,但给它存了long才能存下的数。 产生原因 : 1内存中加载的数据量过于庞大,如一次从数据库取出过多的数据。(主要排查方式 导出,导入。以及排查未分页的查询:表现为对应web页面假死。) 2 JVM 启动参数内存值设定的过小。 3使用的第三方软件中的BUG。 内存泄漏 内存泄漏 (memory leak),是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏危害可以忽略,但内存泄漏堆积后果很严重,无论多少内存,迟早会被占光。Memory leak 最终会导致 out of memory。 内存泄漏对象特点: 1 这些对象是可达的,即在有向图中,存在通路可以与其相连; 2 这些对象是无用的,程序以后不会在使用这些对象。 对象满足这两个条件,可以判定位Java 中的内存泄漏

JVM-垃圾回收机制

风格不统一 提交于 2020-02-05 09:06:02
垃圾回收机制概述: Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有“作用域”的概念,只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存。 ps:内存泄露是指该内存空间使用完毕之后未回收,在不涉及复杂数据结构的一般情况下,Java 的内存泄露表现为一个内存对象的生命周期超出了程序需要它的时间长度,我们有时也将其称为“对象游离”。 垃圾回收简要过程 这里必须点出一个很重要的误区:不可达的对象并不会马上就会被直接回收,而是至少要经过两次标记的过程。 第一次被标记过的对象,会检查该对象是否重写了finalize()方法。如果重写了该方法,则将其放入一个F-Query队列中,否则,直接将对象加入“即将回收”集合。在第二次标记之前,F-Query队列中的所有对象会逐个执行finalize()方法,但是不保证该队列中所有对象的finalize()方法都能被执行,这是因为JVM创建一个低优先级的线程去运行此队列中的方法,很可能在没有遍历完之前,就已经被剥夺了运行的权利。那么运行finalize()方法的意义何在呢?这是对象避免自己被清理的最后手段:如果在执行finalize()方法的过程中,使得此对象重新与GC

JVM内存结构

夙愿已清 提交于 2020-02-05 03:39:38
JVM 内存结构 程序计数器 虚拟机栈 本地方法栈 堆 方法区 一、程序计数器 1.1定义 Program Counter Register 程序计数器(寄存器) 1.2作用 在 java 程序执行前会将 java 文件编译为二进制字节码( jvm 指令) 计数器的作用就是记住下一条 jvm 指令的执行地址(储存在寄存器中) 1.3特点 线程私有 不会存在内存溢出 二、虚拟机栈 (JVM Stacks) 2.1虚拟机栈 每个线程运行时所需要的内存,称为虚拟机栈 栈的特点:先进后出,后进先出 每个栈是由多个栈帧 (Frame) 组成,对应每次方法调用时占用的内存 每个线程只能有一个活动栈帧,对应着当前正在执行的方法 使用虚拟机参数 -Xss【大小】 控制虚拟机栈的空间大小 2.2栈帧 每个方法运行时需要的内存 栈帧中包含的内容 参数 局部变量 返回地址 2.3注意 垃圾回收不涉及栈内存 在方法中的局部变量没有脱离方法的作用范围,则它是线程安全的 若局部变量引用了对象,并脱离了方法的作用范围,则需要考虑线程安全 2.4栈内存溢出 栈帧过多导致栈内存溢出 栈帧过大导致栈内存溢出 2.5线程运行诊断 2.5.1 cpu 占用过多 使用 top 命令定位进程号 使用 ps H -eo pid,tid,%cpu | grep 进程id 定位线程id 使用 jstack 进程id

Java GC调优(上)

烈酒焚心 提交于 2020-02-05 00:52:38
简介 图1 Java-HotSpot是什么? 虚拟机(JVM)版本是25.4-b25 java -version出来信息包含两部分: Java软件包发行版本信息和内核(JVM)版本信息。 java的发行包包含三种类型Java ME,Java SE,Java EE,发行包就相当于对外销售的产品包, 不同发行包会删减部分特性,因此版本信息首先显示发行包类型和版本。 JVM是Java平台的基础和核心,一般在一个java大版本中JVM版本变化都是比较小的。 HotSpot是一种JVM实现技术,相对以往的方式在性能和扩展能力上得到了很大的提升,因此它不是一个独立产品,可以理解Sun(Oracle)实现的JVM版本的品牌商标。 1.JVM体系结构 方法区和堆是GC的作用区。 2.常用的GC算法 1).引用计数算法(Reference Counting GC)简称 直接垃圾回收 图1: 缺点: 1.每次对象赋值,都要对计算器做维护,而且计算器有一定的消耗。 2.循环引用,无法收回,且并不能判断它们是否死亡 注:JVM并不采用此种方式。 2).追踪(Tracing GC ) 简称 间接垃圾收集 标记-清除 (Mark-Sweep) 标记-复制 (Mark-Copying) 标记-整理 (Mark-Compact) 图2: 标记清除(Mark Sweep) 原理: 1.标记 从root开始进行扫描

JVM-学习笔记持续更新

守給你的承諾、 提交于 2020-02-05 00:31:32
1.Java虚拟机的基本结构 (1)类加载子系统与方法区:   类加载子系统负责从文件系统或者网络中加载Class信息,加载的类信息存放在一块称为方法区的内存空间。除了类的信息外,方法区中可能还会存放运行时常量池信息,包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)。 (2)Java堆:   Java堆在虚拟机启动的时候建立,它是JAVA程序主要的内存工作区域,几乎所有的Java对象实例存放在Java堆中。堆空间是所有线程共享的,这是一块与Java应用密切相关的内存空间。 (3)直接内存:   Java的NIO库允许Java程序使用直接内存。直接内存是Java堆外的、直接向系统申请的内存空间。通过访问直接内存的速度优于Java堆。因此出于性能的考虑,读写频繁的场合可能会优先考虑使用直接内存。由于直接内存在Java堆外,因此它的大小不会受限于Xmx指定的最大堆大小,但是系统内存是有限的,Java堆和直接内存的总和依次受限于操作系统能给出的最大内存。 (4)垃圾回收系统:   垃圾回收系统是Java虚拟机的重要组成部分,垃圾回收器可以对方法区、Java堆和直接内存进行回收。其中,Java堆是垃圾收集器的工作重点。和C/C++不同,Java中所有的对象释放都是隐式的,也就是说,Java中没有类似free()或者delete()这样的函数释放指定的内存区域

jvm 虚拟机的组成部分

感情迁移 提交于 2020-02-05 00:24:12
1、 类加载子系统 :负责从文件系统或者网络中加载 Class 信息,加载的信息存放在 一块称之为方法区的内存空间 2、 方法区:存放类信息,常量信息,常量池信息,包括字符串字面量和数字常量等 3、Java 堆:在 java 虚拟机启动的时候建立 java 堆,他是 java 程序最主要的 内存工作区域,几乎所有的对象实例都存放在 java 堆中,堆空间是所有线程共享 的 4、 直接内存: java 的 NIO 库允许 java 程序使用直接内存,从而提高性能,通常 直接内存性能要优于 java 堆。读写频繁的场合可能会有限考虑 5、 栈:每个虚拟机线程都有一个私有的栈,一个线程的 java 栈在线程创建的时候 被创建, java 栈中保存着局部变量、方法参数、同时 java 的调用、返回值等 6、 本地方法栈:调用本地方法,本地方法一般是用 c 编写的 7、 垃圾回收系统:垃圾回收系统是 java 的核心,也是必不可少的, java 有一套 自己进行垃圾清理的机制,开发人员无需手工清理 8、pc 寄存器:寄存器也是每个线程私有的空间, java 虚拟机会为每个线程创建 pc 寄存器,在任意时刻,一个 java 线程总是在执行一个方法,这个方法被称为当前 方法,如果当前方法不是本地方法,则 pc 寄存器的值为 undefined ,寄存器存放 如当前环境指针,程序计数器,操作栈指针

JVM 完整深入解析

末鹿安然 提交于 2020-02-04 22:17:58
工作之余,想总结一下JVM相关知识。 Java运行时数据区: Java虚拟机在执行Java程序的过程中会将其管理的内存划分为若干个不同的数据区域,这些区域有各自的用途、创建和销毁的时间,有些区域随虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束来建立和销毁。Java虚拟机所管理的内存包括以下几个运行时数据区域,如图: 1、程序计数器:指向当前线程正在执行的字节码指令。线程私有的。 2、虚拟机栈:虚拟机栈是Java执行方法的内存模型。每个方法被执行的时候,都会创建一个栈帧,把栈帧压人栈,当方法正常返回或者抛出未捕获的异常时,栈帧就会出栈。 (1)栈帧:栈帧存储方法的相关信息,包含局部变量数表、返回值、操作数栈、动态链接 a、局部变量表:包含了方法执行过程中的所有变量。局部变量数组所需要的空间在编译期间完成分配,在方法运行期间不会改变局部变量数组的大小。 b、返回值:如果有返回值的话,压入调用者栈帧中的操作数栈中,并且把PC的值指向 方法调用指令 后面的一条指令地址。 c、操作数栈:操作变量的内存模型。操作数栈的最大深度在编译的时候已经确定(写入方法区code属性的max_stacks项中)。操作数栈的的元素可以是任意Java类型,包括long和double,32位数据占用栈空间为1, 64 位数据占用2。方法刚开始执行的时候,栈是空的,当方法执行过程中

Java - JVM

邮差的信 提交于 2020-02-04 14:09:09
前言 面向人群及参考书目 Java及JVM简介 Java发展的重大事件 虚拟机与Java虚拟机 虚拟机分为 系统虚拟机 和 程序虚拟机 。 系统虚拟机:Visual Box、VMware - 完全对物理计算机的仿真,提供一个可运行完整操作系统的软件平台。 程序虚拟机:Java虚拟机[JVM] - 专门为执行单个计算机程序而设计,在Java虚拟机中执行的指令我们称为JVM字节码指令[这里不一定是Java字节码,只要是按照JVM规范编译出的字节码文件,Java虚拟机都可以解释运行]。 无论是系统虚拟机还是程序虚拟机,在上面运行的软件都被限制于虚拟机提供的资源中。 Java虚拟机 Java虚拟机是一台直行JVM字节码的虚拟计算机,它拥有独立的运行机制,其运行的Java字节码也未必由Java语言编译而成。 JVM平台的各种语言可以共享Java虚拟机带来的跨平台性、优秀的垃圾回收器,以及可靠的即时编译器。 Java技术的核心就是Java虚拟机(JVM,Java Virtual Machine),因为所有的Java程序都运行在Java虚拟机内部。 作用:Java虚拟机就是二进制字节码的运行环境,负责装载字节码到其内部,解释/编辑对应平台上的机器指令执行。每一条Java指令,Java虚拟机规范中都有详细的定义,如怎么取操作数,怎么处理操作数,处理结果放哪里。 特点 一次编译,到处运行。

JVM第一弹

微笑、不失礼 提交于 2020-02-04 11:56:09
JVM第一弹 基本概念 JVM是可运行java代码的假想计算机,包括一套字节码指令集,一组寄存器,一个栈,一个垃圾回收、堆和一个存储方法域。JVM是运行在操作系统之上的,它与硬件没有直接的交互。 运行过程 我们都知道Java代码源文件,通过编译器能够产生相应的.Class字节码文件,而字节码文件又通过Java虚拟机中的解释器,编译成特定机器上的机器码。 ① Java源文件 ——> 编译器 ——> 字节码文件 ② 字节码文件 ——> JVM ——> 机器码 每种平台的解释器是不同的,但是虚拟机是相同的,这也就是java为什么能够跨平台的原因了。当一个程序从开始运行,这时虚拟机就开始实例化了,多个程序 启动就会存在多个虚拟机实例。 程序退出或者关闭,则虚拟机实例消亡,多个虚拟机实例之间数据不能共享。 类加载器 什么是类的加载? 类的加载是指将类的字节码文件数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。 类的加载的最终产品是位于堆区内中的Class对象,Class对象封装了类在方法区内的数据结构,并且向java程序员提供了访问方法区内的数据结构的接口。 类加载器包括: 启动类加载器(BootStrap) ——主要有C++进行实现的。用来加载jdk安装目录下的:jre/lib下的可执行jar包。