jvm原理

JVM之Java内存结构

。_饼干妹妹 提交于 2019-12-18 04:27:29
Java内存结构的几大部分如下图: 接下来,会对上面每部分区域的功能一一解释。 1、程序计数器:是线程私有区,是内存中一块较小的区域,是当前线程执行的字节码指令的行号指示器,如果线程执行的是Java方法,程序计数器记录的是正在执行的虚拟机字节码指令的地址,如果执行的是native方法,程序计数器存储的是undefined,此区域是内存中唯一一块没有规定任何OutOfMemoryError(内存溢出)情况的区域,为什么?因为我们不需要操作该区域,该区域是内部维护的。 2、虚拟机栈:是线程私有的,该区域所描述的是Java方法执行的动态内存模型,每个方法在执行的时候都会创建一个栈帧,用来存储局部变量表,操作数栈,动态链接,方法出口等信息,局部变量表存放的是编译期可知的基本数据类型,引用类型,returnAddress等,局部变量表的内存在编译期完成分配,进入方法后,这个方法需在帧中分配多少内存是固定的,在方法运行期间不会改变局部变量表的大小。如果说栈帧堆满了整个栈,会出现StackOverflowError(栈溢出)异常,栈也可以申请更大的内存,如果申请不到,会抛出OutOfMemoryError异常。 3、本地方法栈:是为本地的native方法服务的,其他的都和虚拟机栈一样。 4、堆:线程共享的一块区域,用来存放对象实例的(由于现在有了逃逸分析技术,也可以将对象分配在栈上)

YARN 内存参数终极详解

送分小仙女□ 提交于 2019-12-18 04:26:19
很多朋友在刚开始搭建和使用 YARN 集群的时候,很容易就被纷繁复杂的配置参数搞晕了:参数名称相近、新老命名掺杂、文档说明模糊 。特别是那几个关于内存的配置参数,即使看好几遍文档也不能完全弄懂含义不说,配置时一不小心就会张冠李戴,犯错误。 如果你同样遇到了上面的问题,没有关系,在这篇文章中,我就为大家梳理一下 YARN 的几个不易理解的内存配置参数,并结合源码阐述它们的作用和原理,让大家彻底清楚这些参数的含义。 一、YARN 的基本架构 介绍 YARN 框架的介绍文章网上随处都可以找到,我这里就不做详细阐述了。之前我的文章“YARN环境中应用程序JAR包冲突问题的分析及解决”中也对 YARN 的一些知识点做了总结,大家可以在TheFortyTwo 后台回复编号 0x0002 获得这篇文章的推送。下面附上一张 YARN 框架图,方便引入我们的后续内容: 图 1: YARN 架构图 二、内存相关参数梳理 YARN 中关于内存配置的参数呢,乍一看有很多,其实主要也就是那么几个(如果你感觉实际接触到的比这更多更混乱,是因为大部分的配置参数都有新命名和旧命名,我后面会分别解释),我已经整理出来列在了下表中。大家先看一下,对于表中各列的意义,我会在本节后面详细说明;而对于每个参数的意义,我会放在下节进行详细解释。 图 2: 内存参数整理图 下面我们解释一下表中的各列: 配置对象

JVM内存管理------GC简介

十年热恋 提交于 2019-12-18 03:36:54
为何要了解GC策略与原理? 原因在上一章其实已经有所触及,就是因为在平时的工作和研究当中,不可避免的会遇到内存溢出与内存泄露的问题。如果对GC策略与原理不了解的情况下碰到了前面所说的问题,很多时候会让人不知所措。 当我们了解了相关知识以后,虽然有时候依然不能很快的解决问题,但可以肯定的是,至少不会出现无计可施的情况。 GC策略解决了哪些问题? 既然是要进行自动GC,那必然会有相应的策略,而这些策略解决了哪些问题呢,粗略的来说,主要有以下几点。 1、哪些对象可以被回收。 2、何时回收这些对象。 3、采用什么样的方式回收。 GC策略采用的何种算法 有关上面所提到的三个问题,其实最主要的一个问题就是第一个,也就是哪些对象才是可以回收的。 有一种比较简单直观的办法,它的效率较高,被称作 引用计数算法 。但是这个算法有一个致命的缺陷,那就是对于循环引用的对象无法进行回收。想象一下,假设JVM采用这种GC策略,那么程序猿在编写的程序的时候,下面这样的代码就不要指望再出现了。 public class Object { Object field = null; public static void main(String[] args) { Thread thread = new Thread(new Runnable() { public void run() { Object objectA

java之异常

微笑、不失礼 提交于 2019-12-14 14:43:00
异常概念 异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将受影响.在程序中的意思就是: 异常 : 指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止 。 在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。 异常指的并不是语法错误,语法错了,编译不通过,不会产生字节码文件,根本不能运行。 异常体系 异常机制其实是帮助我们找到程序中的问题,异常的根类是 java.lang.Throwable ,其下有两个子类:java.lang.Error 与 java.lang.Exception ,平常所说的异常指 java.lang.Exception 。如下图所示: Throwable体系: Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。要修改错误,必须修改源代码。 Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎。 如下图所示 异常分类 我们平常说的异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。异常(Exception)的分类:根据在编译时期还是运行时期去检查异常? 编译时期异常

大数据计算引擎之 Flink原理与实现:内存管理

不羁岁月 提交于 2019-12-12 15:15:19
转载自: Flink原理与实现:内存管理 本文地址: 大数据计算引擎之 Flink原理与实现:内存管理 如今,大数据领域的开源框架(Hadoop,Spark,Storm)都使用的 JVM,当然也包括 Flink。基于 JVM 的数据分析引擎都需要面对将大量数据存到内存中,这就不得不面对 JVM 存在的几个问题: Java 对象存储密度低。一个只包含 boolean 属性的对象占用了16个字节内存:对象头占了8个,boolean 属性占了1个,对齐填充占了7个。而实际上只需要一个bit(1/8字节)就够了。 Full GC 会极大地影响性能,尤其是为了处理更大数据而开了很大内存空间的JVM来说,GC 会达到秒级甚至分钟级。 OOM 问题影响稳定性。OutOfMemoryError是分布式计算框架经常会遇到的问题,当JVM中所有对象大小超过分配给JVM的内存大小时,就会发生OutOfMemoryError错误,导致JVM崩溃,分布式框架的健壮性和性能都会受到影响。 所以目前,越来越多的大数据项目开始自己管理JVM内存了,像 Spark、Flink、HBase,为的就是获得像 C 一样的性能以及避免 OOM 的发生。本文将会讨论 Flink 是如何解决上面的问题的,主要内容包括内存管理、定制的序列化工具、缓存友好的数据结构和算法、堆外内存、JIT编译优化等。 积极的内存管理 Flink

B4. Concurrent JVM 锁机制(synchronized)

[亡魂溺海] 提交于 2019-12-07 07:08:32
B4. Concurrent JVM 锁机制(synchronized) https://www.cnblogs.com/zlxyt/p/11050346.html 挺好的 感觉这个文章写的 不过想要提高 还是得自己写代码 不写代码 肯定不行. 【 概述 】   JVM 通过 synchronized 关键字提供锁,用于在线程同步中保证线程安全。 【 synchronized 实现原理 】   synchronized 可以用于代码块或者方法中,产生同步代码区域,也叫互斥区。互斥区每次只能允许一个线程进入执行同步代码或重新进入执行剩余同步代码(参考线程进入等待状态后会唤醒,然后进入阻塞状态,重新获得锁的情况)。   synchronized 通过与一个对象进行绑定,或者说对一个对象进行加锁,并产生一个监控对象(monitor object)。如下图所示: 多线程并发执行同步代码,首先多个线程会进入集合(Entry Set),某个时间点只有一个线程可以获得(acquire) 监控对象的锁(monitor lock), 然后执行同步代码块。 如果获得锁的线程执行同步代码完毕,则会释放锁并退出同步代码区域(release and exit)。 若获得锁的线程在执行同步代码时调用被锁住对象的 wait 方法,该线程则会释放(release)锁,并进入集合(Wait Set)。锁被释放后

面试:史上最全多线程面试题 - (锁&内存模型&线程)

一个人想着一个人 提交于 2019-12-06 23:14:33
多线程经典面试题60问。 历史文章: dubbo&zookeeper55道高频面试题(附加答案) SpringCloud&SpringBoot经典面试题(附加答案) 1.什么是活锁、饥饿、无锁、死锁? 死锁、活锁、饥饿是关于多线程是否活跃出现的运行阻塞障碍问题,如果线程出现 了这三种情况,即线程不再活跃,不能再正常地执行下去了。 死锁 死锁是多线程中最差的一种情况,多个线程相互占用对方的资源的锁,而又相互等 对方释放锁,此时若无外力干预,这些线程则一直处理阻塞的假死状态,形成死锁。 举个例子,A 同学抢了 B 同学的钢笔,B 同学抢了 A 同学的书,两个人都相互占 用对方的东西,都在让对方先还给自己自己再还,这样一直争执下去等待对方还而 又得不到解决,老师知道此事后就让他们相互还给对方,这样在外力的干预下他们 才解决,当然这只是个例子没有老师他们也能很好解决,计算机不像人如果发现这 种情况没有外力干预还是会一直阻塞下去的。 活锁 活锁这个概念大家应该很少有人听说或理解它的概念,而在多线程中这确实存在。 活锁恰恰与死锁相反,死锁是大家都拿不到资源都占用着对方的资源,而活锁是拿 到资源却又相互释放不执行。当多线程中出现了相互谦让,都主动将资源释放给别 的线程使用,这样这个资源在多个线程之间跳动而又得不到执行,这就是活锁。 饥饿 我们知道多线程执行中有线程优先级这个东西

细说JVM内存模型

与世无争的帅哥 提交于 2019-12-06 16:13:35
细说JVM内存模型 前言 在正式学习 JVM 内存模型之前,先注意以下几个是问题: JVM 内存模型与 JAVA 内存模型不是同一个概念。JVM 内存模型是从运行时数据区的结构的角度描述的概念;而 JAVA 内存模型是从主内存和线程私有内存角度的描述。从以下两张图可以看出: ​ JAVA内存模型 ​ JVM内存模型 Java虚拟机总共由三大模块组成: 类加载器子系统 运行时数据区执行引擎 本篇我们介绍第二大模块——运行时数据区(JVM内存模型)。 其实虚拟机的这些模块并不是独立的,都是相互联系的。java 文件编译为 class 文件,通过类加载子系统加载,信息再到 JVM 托管的内存中(部分操作会与本地内存交互)的流转,再到垃圾回收等等,都是一系列的操作。 本系列的博客为了更加清晰的描述清楚功能和原理,将其分为几个章节写作。 概览 运行时数据区分为几大模块(如上图所示): 线程共享区: JAVA堆 方法区 线程私有区: JAVA栈 本地方法栈 程序计数器 本文中,我们将从以下几个方法面来分析各个区域: 功能 存储的内容 是否有内存溢出和内存泄露 是否进行垃圾回收 对应的垃圾回收算法 垃圾回收流程 性能调优 线程私有区 程序计数器 程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器

Eclipse远程调试Tomcat

删除回忆录丶 提交于 2019-12-06 11:01:14
最近,一直在研究Tomcat的工作内幕,主要的方法就是参考 《How Tomcat Works》 这本书和Tomcat 5.5.26的源代码。 Tomcat的代码结构还是比较清晰的,注释也比较全。但是代码毕竟是静态的,难以彻底弄清类与类之间的协作关系,以及运行时对象的交互关系。 如果能对Tomcat的启动、处理请求和停止的过程进行断点调试,看清Tomcat的每一步行踪,那么就能解决上面的问题了。 于是,又一个问题出来了: 如何使用Eclipse远程调试Tomcat ? 上网查了一些资料,相关的文章还是很多的。我简单梳理了一下解决方案及原理,顺便熟悉了Tomcat的启动脚本。 如何远程调试JVM? 远程调试Tomcat,本质上就是远程调试JVM。倒不是需要了解JVM自身的运行细节,而是要了解JVM上应用程序的运行细节。 无论如何,我们都要获取JVM运行时的内部信息(比如查看调试信息),并对JVM的运行流程进行控制(比如单步执行),才能达到调试的目的。 这个事情光靠调试器本身,肯定是做不到的。不然,JVM的安全性就大打折扣了。除非JVM提供某种“后门”,供调试器查询一些运行时信息,并允许调试器发送一些控制命令。 不得不感慨,JVM的强大。从J2SE 1.4.2开始,就已经提出并实现了 Java TM Platform Debugger Architecture ,简称JPDA。

【并发编程】synchronized的使用场景和原理简介

丶灬走出姿态 提交于 2019-12-05 04:38:58
1. synchronized使用 1.1 synchronized介绍 在多线程并发编程中synchronized一直是元老级角色,很多人都会称呼它为重量级锁。但是,随着Java SE 1.6对synchronized进行了各种优化之后,有些情况下它就并不那么重了。 synchronized可以修饰普通方法,静态方法和代码块。 当synchronized修饰一个方法或者一个代码块的时候,它能够保证在同一时刻最多只有一个线程执行该段代码。 对于普通同步方法,锁是当前实例对象(不同实例对象之间的锁互不影响)。 对于静态同步方法,锁是当前类的Class对象。 对于同步方法块,锁是Synchonized括号里配置的对象。 当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。 1.2 使用场景 synchronized最常用的使用场景就是多线程并发编程时线程的同步。这边还是举一个最常用的列子:多线程情况下银行账户存钱和取钱的列子。 public class SynchronizedDemo { public static void main(String[] args) { BankAccount myAccount = new BankAccount("accountOfMG",10000.00); for(int i=0;i<100;i++){ new