经过上一篇文章铺垫了一些对象分配的基础知识后,想必大家现在都心里非常有数了,咱们平时代码里创建出来的对象,一般就是两种:
Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。这个区域是用来存放对象实例的,几乎所有对象实例都会在这里分配内存。平常我们听说的垃圾收集、GC等名词都是由堆发展而来的
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
Java堆是虚拟机所管理的内存中最大的一块,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这块区域是“线程共享”的。
Java堆是被所有线程共享的一块内存区域,所有对象和数组都在堆上进行内存分配。为了进行高效的垃圾回收,虚拟机把堆内存划分成新生代、老年代和永久代(1.8中无永久代,使用metaspace实现)三块区域
参考文献: http://www.importnew.com/14630.html Java 堆内存 http://blog.csdn.net/ylyg050518/article/details/52244994 Java虚拟机(二)——Java堆内存划分
Java虚拟机根据对象存活的周期不同,把堆内存划分为几块,一般分为新生代、老年代和永久代(对HotSpot虚拟机而言),这就是JVM的内存分代策略。
在读博士的时候,我曾经写过一个统计 Java 对象生命周期的动态分析,并且用它来跑了一些基准测试。
Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。
大部分的Java对象只存活一小段时间,而存活下来的小部分Java对象则会存活很长一段时间
目前JVM提供的正式垃圾回收器有并行、串行、CMS和G1。这四种垃圾回收器都是基于分代内存管理。分代管理就是把内存划分成不同的区域进行管理,其思想来源是:有些对象存活的时间短,有些对象存活的时间长,把存活时间短的对象放在一个区域管理,把存活时间长的对象放在另一个区域管理,那么可以为两个不同的区域选择不同的算法,加快垃圾回收的效率。我们假定内存被划分成2个代,新生代和老生代。把容易死亡的对象放在新生代,通常采用复制算法回收,把预期存活时间较长的对象放在老生代,通常采用标记清除算法。
关于 JVM 内存模型以及垃圾回收的文章网上很多,自己以前也看过很多,但是却从来也没有系统的去了解学习过,这次正巧看到一本讲解 JVM 的好书 – 周志明老师的《深入理解 Java 虚拟机》,然后就花了点时间,认真系统的学习了一遍,尽管还没有看完,但是已经爱耐不住,觉得要写点东西出来,写的过程是一个思考融汇的过程,也是一个知识升华的过程。
Java所承诺的自动内存管理主要是针对对象内存的回收和对象内存的分配。 在Java虚拟机的五块内存空间中,程序计数器、Java虚拟机栈、本地方法栈内存的分配和回收都具有确定性,一般在编译阶段就能确定需要分配的内存大小,并且由于都是线程私有,因此它们的内存空间都随着线程的创建而创建,线程的结束而回收。也就是这三个区域的内存分配和回收都具有确定性,垃圾回收器不需要在这里花费太大的精力。 而Java虚拟机中的方法区因为是用来存储类信息、常量、静态变量,这些数据的变动性较小,因此不是Java内存管理重点需要关注的区
我们说Java是自动进行内存管理的,所谓自动化就是,不需要程序员操心,Java会自动进行内存分配和内存回收这两方面。
所谓垃圾就是内存中已经没有用的对象。 既然是”垃圾回收",那就必须知道哪些对象是垃圾。Java 虚拟机中使用一种叫作可达性分析的算法来决定对象是否可以被回收。
-Xms 、-Xmx、-XX:newSize、-XX:MaxnewSize、-Xmn(-XX:newSize、-XX:MaxnewSize)
小白:(是不是太基础了,暗笑)byte[] arrays = new byte[1024]。
3. 当再次进行Minor GC时,之前作为To Space的S0或S1则转换为From Space,通常存活的对象在Minor GC后并不是直接进入旧生代,只有经历过几次Minor GC仍然存活的对象,才放入旧生代中,这个在Minor GC中存活的次数在串行和ParNew方式时可通过-XX:MaxTenuringThreshold来设置,在ParallelScavenge时则由Hotspot根据运行状况来决定。当ToSpace空间满,剩下的存活对象则直接转入旧生代中。
Java中堆是JVM所管理的最大的一块内存空间,主要用于存放各种类的实例对象和数组,如下图所示:
Java堆(Java Heap)是JVM所管理的最大内存区域,也是所有线程共享的一块区域,在JVM启动时创建。
为了解决 Mark-Sweep 算法内存碎片化的缺陷而被提出的算法。按内存容量将内存划分为等大小 的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用 的内存清掉,如图:
在Java中,它的内存管理包括两方面:内存分配(创建Java的时候)和内存回收,和C不同,这方面读是由JVM来完成的,避免了C/C++直接操作的风险,同时也降低了学习Java的难度。虽然内存管理完全由JVM负责,但是如果程序员不了解内存分配,就会导致高耗内存、内存泄露等问题。所以Java程序员还是要学习JVM的内存回收机制。才能写出更高效的代码。
本次讲述jvm分代模型的基础概念,这个专栏会由浅入深的不断构建起来,循序渐进,和上一篇一样,是非常基础的内容
所谓虚拟机,就是一台虚拟的机器。他是一款软件,用来执行一系列虚拟计算指令,大体上虚拟机可以分为:系统虚拟机和程序虚拟机, 大名鼎鼎的Visual Box、Vmare就属于系统虚拟机,他们完全是对物理计算的仿真,提供了一个可以运行完整操作系统的软件平台。
为什么划分老年代和新生代,主要对象大小不一样,对象生命周期不一样。划分后,提供垃圾回收效率,节省资源,提升对象利用率等等。
Heap(堆区) New Generation(新生代) Eden 伊甸园 Survivor From Survivor To Old Generation(老年代) 方法区 Permanent Generation(持久代) Stack(栈区) Metaspace(元空间) Direct ByteBuffer(堆外内存) 通过JVM启动参数来配置以上内存空间 Heap(堆)内存大小设置 -Xms512m 设置JVM堆初始内存为512M -Xmx1g 设置JVM堆最大可用内存为1G New Generation(新生代)内存大小设置 -Xmn256m 设置JVM的新生代内存大小(-Xmn 是将NewSize与MaxNewSize设为一致。256m),同下面两个参数 -XX:NewSize=256m -XX:MaxNewSize=256m
Java所承诺的自动内存管理主要是:给对象分配内存,回收分配给对象的内存. 在Java虚拟机的五块内存空间中,程序计数器、Java虚拟机栈、本地方法栈内存的分配和回收都具有确定性,一般在编译阶段就能确定需要分配的内存大小,并且由于都是线程私有,因此它们的内存空间都随着线程的创建而创建,线程的结束而回收.也就是这三个区域的内存分配和回收都具有确定性,垃圾回收器不需要在这里花费太大的精力. 而Java虚拟机中的方法区因为是用来存储类信息、常量、静态变量,这些数据的变动性较小,因此不是Java内存管理重点需要关注
对象分配过程:TLAB(Thread Local Allocation Buffer)
在Java中,垃圾收集机制(Garbage Collection)是一种自动的管理内存的机制,用于回收不再使用的对象所占的内存空间。
需要提前了解的知识点: JVM内存模型 JVM垃圾回收算法 下图是JVM内存区域划分的逻辑图 JVM内存区域逻辑图 从图中我们大概了解JVM相关的内存区域。 JVM内存包括区域 Heap(堆区) Ne
上篇文章我们聊了JVM的内存模型,知道了堆是JMM中最大的一块,也是垃圾收集最急需解决的一块内存区域。今天我们就来唠唠JVM的GC算法。
前言 在本系列上一篇文章中我讲到了垃圾标记算法,垃圾被标记后,GC就会对垃圾进行收集,垃圾收集有很多种算法,这篇文章就来介绍常用的垃圾收集算法的思想。 1.标记-清除算法 标记-清除算法(Mark-S
对象的内存分配,就是在堆上分配(也可能经过 JIT 编译后被拆散为标量类型并间接在栈上分配),对象主要分配在新生代的 Eden 区上,少数情况下可能直接分配在老年代,**分配规则不固定**,取决于当前使用的垃圾收集器组合以及相关的参数配置。
JVM 是可运行 Java 代码的假想计算机 ,包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收,堆 和 一个存储方法域。JVM 是运行在操作系统之上的,它与硬件没有直接的交互。
Java堆内存被划分为新生代和年老代两部分,新生代主要使用复制和标记-清除垃圾回收年老代主要使用标记-整理垃圾回收算法,因此 java 虚拟中针对新生代和年老代分别提供了多种不同的垃圾收集器,JDK1.6 中 Sun HotSpot 虚拟机的垃圾收集器如下:
1.堆的核心概述 1.1 认识堆内存 堆与进程、线程 一个进程对应一个JVM实例 一个JVM实例对应一个堆空间 进程包含多个线程,所以线程之间共享同一个堆空间 对堆的认识 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域。 Java堆区在JVM启动的时候即被创建,其空间大小也就确定了,堆是JVM管理的最大一块内存空间。 堆内存的大小是可以调节的。 《Java虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的。 所有的线程共享Java堆,在这里还可以划分线
一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序。程序开始执行时他才运行,程序结束时他就停止。你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机。 Java虚拟机总是开始于一个main()方法,这个方法必须是公有、返回void、直接受一个字符串数组。在程序执行时,你必须给Java虚拟机指明这个包换main()方法的类名。main()方法是程序的起点,他被执行的线程初始化为程序的初始线程。程序中其他的线程都由他来启动。
对于jvm来说垃圾是指运行程序中没有任何指针指向的对象,这个对象就需要被回收。
suorce:https://www.cnblogs.com/haha66/p/13821842.html
http://www.importnew.com/18694.html
初始化堆的当前内存使用量:init = 31457280(30720K) used = 2083952(2035K) committed = 30408704(29696K) max = 30408704(29696K)
Java堆:一般是放置实例化的对象的地方,堆分新生代和老年代空间,不断未被回收的对象越老,被放入老年代空间。分配最大堆空间:-Xmx 分配初始堆空间:-Xms,分配新生代空间:-Xmn,新生代的大小一般为整个堆空间的1/3到1/4。新生代一般分为eden和survivor(from,to)区。新生代被GC15(配置参数-XX:MaxTenuringThreshold,默认15)次后仍存活,进入老年代,但也可能提前晋升,由survivor区决定。新生代和老年代都属于JVM的Heap区,另外还有一个持久代Perm区,又叫永久区,是一块线程共享的内存区域,大小决定了系统可以保存多少个类,定义太多的类,会抛出内存溢出错误。分配永久区空间:-XX:PermSize和-XX:MaxPermSize(默认为64M)。
不论是正经或者不正经的程序猿要想变强不能光光变秃,你还必须掌握JVM相关的底层知识。
本文内容是基于 JDK 1.6 的,不同版本虚拟机之间也许会有些许差异,但不影响我们对JVM垃圾回收机制的整体把握和了解。
Java的垃圾回收,我们都知道写Java程序的时候,是不考虑内存分配的。是由jvm底层回收释放内存的。可以通过system.gc手动释放,但是是不是会立刻执行全靠jvm内部自己决定。这里我们用jdk1.7举例子说明,主要是jdk1.7和jdk1.8的区别比较大.jdk1.8多了一个元数据区,没有永久区。直接从物理机上分配内存,极少会出现oom.(内存溢出)。我们可以用jvm自带的命令行工具,这里要注意一下要用oracle版本的,不要Linux自带的openjdk.我们敲击jps就能看到Java进程,在用js
现在面试Java开发时,基本都会问到Java虚拟机的知识,根据职位不同问的内容深浅又有所区别。本文整理了10道面试中常问的Java虚拟机面试题,希望对正在面试的同学有所帮助。
领取专属 10元无门槛券
手把手带您无忧上云