OutOfMemoryError
,详情见 【拒绝一问就懵】之不可忽视的内存泄露。程序计数器是线程私有的内存区域,这个区域是Java虚拟机中惟一一个没有限制OutOfMemoryError
的内存区域。之因此须要它是由于Java的多线程机制是经过轮流切换分配处理器执行时间来实现的,因此会涉及到线程的暂停和重启,而在一个线程中若是正在执行Java方法的话,这个计数器就回去记录当前正在执行的虚拟机字节码,一旦被暂停,恢复只须要从程序计数器记录的为止继续执行就能够。程序员
可是,若是线程中执行的是一个Native方法,那么程序计数器是不会去记录的,因此此时的程序计数器为空。算法
Java虚拟机栈也是线程私有的。一条线程启动就会为它创建一个虚拟机栈。数组
在线程中每有一个Java方法被调用就会建立一个 “栈帧” 。每一个 “栈帧” 会保存执行该方法所需的局部变量表(通常Java程序员喜欢用这个部分来表明栈)、操做数栈、动态连接以及方法出口等信息。安全
若是一个线程中有过多的 “栈帧” 要入到虚拟机栈中,即短期内调用了过多的方法,就会形成 -- 栈益处 -- ,即 StackOverflowError 错误。bash
在这个内存区域中,若是虚拟机须要扩展内存,但没有申请到足够的内存,就会抛出 OutOfMemoryError 错误。多线程
和虚拟机栈有些相似,但它是为Native方法提供服务的。并发
Java的堆内存是Java虚拟机所管理的内存中最大的一块。它是全部线程所共享的,用于存放对象实例和数组,Java虚拟机的GC主要就发生在这个地方。所以这块区域也叫作"GC堆"。工具
Java堆的内存能够按照垃圾回收算法【分代回收】分为【新生代区】和【老年区】,进一步的,【新生代区】能够分为【Eden区】、【From Survivor区】和【To Survivor区】。post
从内存角度来讲,Java堆内存又被划分为线程共享的内存区域和每一个线程私有的内存区域。spa
在Java堆区域中,若是没有内存分配给要建立的实例,而且堆也不可以再扩展,就会抛出OutOfMemoryError
错误。
在Java8以后,Heap Segment真正意义上的是由Young Generiation和Old Generiation组成的。对象在其中是标记复制算法来断定一个对象是否应该被清理掉。
Heap Segment中发生的GC称为Major GC,只会影响Heap Segment区。
这个区域发生的GC称为Minor GC
。
-XX:MaxTenuringThreshold
该命令来调整阀值)时,这个对象将被复制到Old Generiation区中,此时该对象将会变的相对安全,由于Old Segment区的GC频率相对较低。这个区域发送的GC成为Full GC
。
OutOfMemoryError
。Java的方法区和Java的堆内存同样是被线程所共有的。它主要存放虚拟机加载的类信息、常量、静态变量、即时编译产生的代码等。
一些地方会将方法区合并到Java堆中一块儿去说。把它做为“永久代”。这在Hot-Spot虚拟机而言成立,可是通常来讲是不成立的。
Java的方法区若是内存不够分配的话,也是会抛出OutOfMemoryError
错误的。也就是若是加载过多类到方法区的话,可能会形成方法区内存益处。
在GC检查对象的是否能够回收时,是根据对象是否可到达引用练顶端的GC Roots
对象来判断的。GC Roots
对象通常是虚拟机栈中变量表中引用的对象、类静态属性引用的对象、常量对象、JNI传到底层的对象。就是说,一个对象若是溯源不到这几种类型的对象的话,就认为它是没法到达的,那么它将会在GC时被回收。
在JDK 1.2以后,Java扩充了4种引用类型定义:
即咱们平时经过new关键字建立出来的的对象的引用,只要强引用还存在,那么这些对象就必定不回被回收,即便时抛出OutOfMemoryError
。何时强引用会不存在呢?当一个方法执行完,栈帧中的变量表将会被清理,在该方法中建立使用的临时强引用就会被清理掉,以后,本来它指向的对象就被变的不可到达。
用来描述一些有用但不是必须的对象,即经过SoftReference
建立的对象,它们将会在本来肯定要发生内存溢出前的一次GC中被回收,若是回收完内存仍是不够,Java堆就会抛出OutOfMemoryError
错误。就是说,在触发内存溢出发生前,这些对象是和强引用同样,只要引用还在,就不会被回收。
用来描述一些没必要须的对象,即经过WeakReference
建立的对象。弱引用对象的生命周期只有一次GC。
一个对象的存在与否彻底不受虚引用的影响,它惟一的用处就是能够用来监测一个对象是否被回收。
运行时常量池主要存放类中编译时期生成的常量,固然也能够动态的往里面添加。
好比:
"abc".intern();
复制代码
这个方法首先会检查运行时常量池中是否有这个字符串,有的话取出来用,没有的话生成一个并存到常量池中。
再好比,运行过程当中生成经过static
修饰的String时,也会加入到常量池中。对于String而言,常量 + 常量
生成的也是常量,可是常量 + 变量
生成的就是变量了。
Dalvik虚拟机是Google按照JVM虚拟机规范定制的虚拟机,它更符合移动设备的环境要求。与标准虚拟机不一样:
.dex
文件,这种格式的文件体积更小。而JVM规范的是.class
文件。ART虚拟机在Android 5.0之后是被默认开启的,此时Dalvik已经被Google放弃维护了。它与Dalvik虚拟机的不一样:
看到这里的童鞋快奖励本身一口辣条吧!
想要看CoorChice更多的文章,能够加个关注哦!