jvm

初始JVM

a 夏天 提交于 2020-03-01 20:04:05
这几天面试,问了一些JVM的知识感觉答的不是很好,在此写JVM系列的文章(再次讨论的是java8的相关知识点),回顾一下相关知识,希望能够帮到看我文章的朋友,现在马上开始。 相关概念: 1.什么是jvm?(java virtual machine) Java虚拟机是抽象的计算机。像真正的计算机一样,它具有指令集并在运行时操作各种内存区域。 2.什么是运行时数据区? Java虚拟机定义了在程序执行期间使用的各种运行时数据区域。其中一些数据区域是在Java虚拟机启动时创建的,仅在Java虚拟机退出时才被销毁。其他数据区域是每个线程的。创建线程时创建每个线程的数据区域,并在线程退出时销毁每个数据区域。 The Java Virtual Machine defines various run-time data areas that areused during execution of a program. Some of these data areas are created on Java Virtual Machine start-up and are destroyed only whenthe Java Virtual Machine exits. Other data areas are per thread.Per-thread data areas are

三:JVM学习-内存分配以及回收策略

六眼飞鱼酱① 提交于 2020-03-01 17:44:13
java技术体系中所提倡的自动内存管理最后可以归结为自动化解决两个问题:给对象分配内存以及回收分配给对象的内存,关于回收内存,上一篇已经说了很多JVM内部的垃圾收集器体系以及他运行的垃圾收集算法,现在我们在探讨一下给对象分配内存的时候需要注意的事项。 对象的内存分配,大的讲,就是在java heap上分配,对象主要分配在新生代的Eden空间上,如果启用了本地线程缓冲分配,那么将按照线程优先在TLAB上分配,少数情况也可能直接分配在老年代。但是分配的原则不是百分之百固定的,还要取决你采用的那种垃圾收集器的二组合,以及虚拟机中内存设置的相关参数。 1:对象优先在Eden上分配 大多数情况下,对象在新生代Eden区域中进行分配,档Eden区域中没有足够的空间进行分配的时候,发起一次Minor GC 注意提到的Minor GC和Full GC Minor GC:这就是新生代的GC,指的是新生的垃圾收集动作,由于java对象大多具有朝生夕死的特性,所以Minor GC非常频繁,一般回收速度也比较快。 Full GC:指的是发生在老年代的GC,又被称作Major GC,出现了Major GC,经常会伴随这至少一次的Minor GC,但这也不是绝对的,一般来说Major GC的速度会比Minor GC慢十倍以上。 2:大对象直接进入老年代

JVM层GC调优(上)

混江龙づ霸主 提交于 2020-03-01 16:47:10
JVM内存结构简介(jdk1.8) JVM层的GC调优是生产环境上必不可少的一个环节,因为我们需要确定这个进程可以占用多少内存,以及设定一些参数的阀值。以此来优化项目的性能和提高可用性,而且这也是在面试中经常会被问到的问题。 想要进行GC调优,我们首先需要简单了解下JVM的内存结构,Java虚拟机的规范文档如下: https://docs.oracle.com/javase/specs/jvms/se8/html/index.html 在介绍JVM内存结构之前,我们需要先知道 运行时数据区 这样的一个东西,它与JVM的内存结构有着一定的关联。不过它属于是一个规范,所以与JVM内存结构是有着物理上的区别的。运行时数据区如下: 1.程序计数器(Program Count Register,简称PC Register): JVM支持多线程同时执行,每一个线程都有自己的PC Register。当每一个新线程被创建时,它都将得到它自己的PC Register。线程正在执行的方法叫做当前方法。如果执行的是Java方法,那么PC Register里存放的就是当前正在执行的指令的地址,如果是native方法(C/C++编写的方法),则是为空。此内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。 2.虚拟机栈(JVM Stacks): Java虚拟机栈

JVM内存结构

天大地大妈咪最大 提交于 2020-03-01 16:41:22
1.jdk、jre、jvm jdk包含jre,jre包含jvm. jdk是一个合集,包括一些编译工具 jre是Java运行环境,包含一些插件 jvm是最基础的,做翻译的,将class翻译成操作系统是的指令(0101) 2.运行时数据区 线程私有 :程序计数器、虚拟机栈、本地方法栈 线程共享 :堆、方法区 程序计数器 (唯一不会OOM的区域):记录指向当前线程正在执行的字节码指令的地址(行号) Java是多线程的,意味着线程切换,确保多线程情况下的程序正常执行。 栈 (stack):一种数据结构 为什么jvm要使用栈?答:更好的兼容方法调用方法的特点。 虚拟机栈 (大小设置 -Xss 1M,虚拟机栈就是在栈数据结构上的一个种拓展):存储当前线程运行方法所需的数据,指令、返回地址 栈帧 :多个方法,每个方法就是一个栈帧 方法转换为字节码,在虚拟机中运行过程 栈默认大小为1M,StackOverFlowError(栈溢出)的出现是因为方法死递归调用本方法,导致内存超出1M。 OOM栈内存溢出,很多线程在跑,10万个线程栈空间就是10万*1M,导致内存不足。 本地方法栈 :是保存的native方法信息,jvm调用后,jvm不为其在虚拟机中创建栈帧,jvm只是简单动态并直接调用native方法。 方法区 (永久代jdk1.7及以前,元空间jdk1.8):存放类信息、常量(final)

JVM中的对象

柔情痞子 提交于 2020-03-01 16:31:47
划分对象 两种方式: 指针碰撞:java内存空间规整的请款下使用 空闲列表:java内存空间不规整的请款下使用 并发安全问题:频繁创建对象就会存在线程不安全问题。解决方案有两种: 1.对分配内存空间的操作进行同步处理,CAS加失败重试机制保证保证更新操作原子性。 2.分配缓冲:给每个线程分配独立空间(Java堆中申请一小块私有内存),也就是本地线程分配缓冲(Tread Local Allocation Buffer,TLAB),开启 -XX:+UseTLAB,在自己Buffer分配,空间不够重新在Eden区申请一块继续使用。 TLAB可以让每个应用线程拥有专属的分配指针来分配空间(Eden区,默认Eden的1%),减小同步开销。 TLAB只是让每个线程有私有的分配指针,但底下存对象的内存空间还是给所有线程访问的,只是其他线程无法在这个区域分配而已。当一个TLAB用满(分配指针top撞上分配极限end了),重新申请一个TLAB. 对象内存布局 在HotSpot虚拟机中,对象的内存布局分为:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding) 对象头分配两部分,一是自身运行时数据(哈希吗HashCode)、GC分带年龄、锁状态标志、线程持有锁、偏向线程ID、偏向时间戳等。 另一种类型指针,即只想它的类元素指针,虚拟机通过这个指针来确定是哪个类的实例

优化Java堆大小的5个技巧

梦想的初衷 提交于 2020-03-01 15:07:31
本文作者Pierre是一名有10多年经验的高级系统架构师,他的主要专业领域是Java EE、中间件和JVM技术。根据他多年的工作实践经验,他发现许多性能问题都是由Java堆容量不足和调优引起的。下面他将和大家分享非常实用的5个Java堆优化技巧。 1.JVM:对难以理解的东西产生恐惧感 千万不要以为,通过配置,调优,就可以排除那些你所不明白的问题。有些人认为Java程序员不需要知道内部JVM内存管理。毫无疑问,这种观点明显是错误的,如果想拓宽知识面和提升排除故障能力,你就必须要了解和学习一下JVM内存管理。 对于Java或者是Java EE新手来说,Java Heap调优和故障排除是一项非常有挑战的工作。下面会提供一些典型的案例场景: 客户端环境面临着有规律的OutOfMemoryError错误并且对业务造成了很大的影响。 你的开发团队要在如此大的压力下去解决这个问题,通常会怎么做? 用谷歌搜索引擎找到类似的问题并且你会相信(或假设)你也面临同样的问题。 你会抓住JVM-Xms和存在OutOfMemoryError异常这几个关键字的例子,然后希望通过这样的案例来快速解决客户端问题。 最后你会在你环境中使用相同的调优方法。两天后,问题仍然发生(甚至更糟或者稍微好点)…… 到底是哪里错了呢? 首先,没有摸清问题根源所在?对开发环境没有正确地进行深层面(规格、负载情况等)理解

简单了解下Synchronized加锁和释放锁的JVM指令

允我心安 提交于 2020-03-01 12:58:24
示例代码 public class TestMain { private Object lock = new Object ( ) ; public void get ( ) { synchronized ( lock ) { System . out . println ( "get" ) ; } } } 通过javap命令把TestMain的字节码文件反编译成JVM指令 javap - verbose TestMain . class 部分结果如下: 这里monitorexit有两个是因为线程出现异常后也会释放锁,所以monitorexit的数量会比monitorenter的数量多,无需一一对应,入口只能有一个,这是为了同步,出口可以有多个,这是为了尽量保证在不同情况下,锁都能够被顺利释放。 总结 这篇文章主要就是看下Synchronized加锁和释放锁的JVM指令是什么样的,具体细节没有做深入,可以发现 Synchronized靠的是monitorenter和monitorexit两个JVM指令配合做到加锁和释放锁的操作。 来源: CSDN 作者: 绅士jiejie 链接: https://blog.csdn.net/weixin_38106322/article/details/104578641

jvm(二)、类的加载机制

浪子不回头ぞ 提交于 2020-03-01 12:22:37
一、类的加载过程 当程序主动使用某个类时,如果该类还未被加载到某个类中,则系统会经过以下三个步骤对该类初始化。 二、类的加载与ClassLoader的理解。 加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生产一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口(即引用地址)。所有需要访问和使用类数据只能通过这个Class对象。这个加载过程需要类加载器参与。 链接:将java类的二进制代码合并到jvm的运行状态之中的过程。   验证:确保加载的类信息符合jvm规范,如:以cafe开头,没有安全方面的问题。   准备:正是为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。    解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。 初始化:执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译期自动收集类中所有变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。   初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先出发其父类的初始化。   虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确枷锁和同步。 三、类加载器的作用 类加载器的作用

JVM学习五:JVM之类加载器之编译常量和主动使用

折月煮酒 提交于 2020-03-01 12:08:40
在学习了前面几节的内容后,相信大家已经对JAVA 虚拟机 加载类的过程有了一个认识和了解,那么本节,我们就继续进一步巩固前面所学知识和特殊点。 一、类的初始化回顾 类在初始化的时候,静态变量的声明语句以及静态代码块都被看作类的初始化语句,Java虚拟机会按照初始化语句在类文件中的先后顺序来依次加载它们。 上图中a的初始化其实经过了四步 1、a被初始化为默认值0 2、a被赋予正确的初始值1 3、执行静态代码块,将a的值赋为2 4、执行静态代码块,将a的值赋为4 因此最终的执行结果是4,一个类只能被一个ClassLoader加载一次,只有没有被加载过的类或者已经被卸载的类才可能被再次加载。类的初始化步骤如下: 1、假如这个类还没有被加载和连接,那就先进行加载和连接 2、假如存在直接的父类,并且这个父类还没有被初始化则先初始化直接的父类 3、假如类中存在初始化语句,那就依次执行初始化语句。 注意:Java虚 拟机在初始化一个类的时候要求它的父类已经被初始化,但是这条规则并不适应于接口!在初始化一个类的时候并不会初始化他所实现的接口!在初始化一个接口的 时候也不会去初始化他的父接口!因此一个父接口并不会因为他的实现类或者子接口的初始化而初始化,只有当程序使用该接口特定的静态变量的时候才会去初始化 这个接口! 我们上面的例子印证了第三点,对于前两点我们知道我们构造一个类的时候假设它有父类

JVM基础:深入学习JVM堆与JVM栈

﹥>﹥吖頭↗ 提交于 2020-03-01 11:18:08
个人博客导航页(点击 右侧 链接 即可打开个人博客): 大牛带你入门技术栈 以前堆是干啥栈是干啥都知道,就是没连在一起想想。感觉讲的不错的一篇儿~~JVM栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;JVM堆解决的是数据存储的问题,即数据怎么放、放在哪儿,另外JVM堆中存的是对象。JVM栈中存的是基本数据类型和JVM堆中对象的引用。 JVM基础概念:JVM堆与JVM栈 数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型。基本类型的变量保存原始值,即:他代表的值就是数值本身;而引用类型的变量保存引用值。“引用值”代表了某个对象的引用,而不是对象本身,对象本身存放在这个引用值所表示的地址的位置。 基本类型包括:byte,short,int,long,char,float,double,Boolean,returnAddress 引用类型包括:类类型,接口类型和数组。 JVM堆与JVM栈 JVM堆和JVM栈是程序运行的关键,很有必要把他们的关系说清楚。 JVM栈是运行时的单位,而JVM堆是存储的单位。 JVM栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;JVM堆解决的是数据存储的问题,即数据怎么放、放在哪儿。 在Java中一个线程就会相应有一个线程JVM栈与之对应,这点很容易理解,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程JVM栈。而