JVM内存管理学习总结

1.      Java程序从源码编译成字节码和从字节码编译成本地机器码的这两个过程,合并起来其实就是等同于一个传统的编译器所执行的编译过程。

2.      Java语言和虚拟机提供了原生的、完善的多线程支持,使得它天生就适合开发多线程并发的应用程序。

3.      Java API类库中的JavaSEAPI子集和java虚拟机这两部分统称为JRE(java RunTime Environment),JRE是支持Java程序运行的标准环境。

4.      一个运行时的java虚拟机实例的天职是:负责运行一个java程序。当启动一个程序时,一个虚拟机实例也就诞生了。当程序关闭退出,这个虚拟机实例也就随之消亡了。如果同一台计算机上同时运行了三个java程序,将得到三个java虚拟机实例。每个java程序都运行于它自己的java虚拟机实例中。

5.      Java虚拟机实例通过调用某个初始类的main方法来运行一个java程序。而这个main方法必须是公有的静态的,返回值为void,并且接受一个字符串数组作为参数。任何拥有这样一个main方法的类都可以作为java程序运行的起点。

6.      主要还有任何非守护线程在运行,那么这个java程序也在继续运行。当该程序中的所有非守护线程都终止时,虚拟机实例将自动退出。假若安全管理器允许,程序本身也能够通过调用Runtime类或者System类的exit方法来退出。

7.      每个java虚拟机实例都有一个方法去以及一个堆,它们是由该虚拟机实例中所有线程共享的。当虚拟机装在一个class文件时,它会从class文件中包含的二进制数据中解析类型信息。然后把这些类型信息放到方法区中。当程序运行时,虚拟机会把所有该程序在运行时创建的对象放到堆中。

8.      当一个新线程被创建时,它都将得到它自己的PC寄存器(程序技术器)以及一个java栈,如果线程正在执行的是一个java方法,那么PC寄存器的值将总是指向下一条将被执行的指令,而它的java栈则总是存储该线程中java方法调用的状态—包括它的局部变量,被调用时传进来的参数,返回值,以及运算的中间结果等等。而本地方法调用的状态,则是以某种依赖于具体实现的方法存储在本地方法栈中,也可能是在寄存器或者其他某些与特定实现相关的内存中。

9.      Java语言中的所有基本类型同样也都是java虚拟机中的基本类型。但是boolean有点特别,虽然java虚拟机也把boolean看做基本类型,但是指令集boolean只有很有限的支持,当编译器把java源代码编译为字节码时,它会用int或者byte来表示boolean。在java虚拟机中,false是由整数0来表示的,所有非零整数都表示为true,涉及boolean值的操作则会使用int。

10.  Java虚拟机中还有一个只在内部使用的基本类型:returnAddress,java程序员不能使用这个类型,这个基本类型被用来实现java程序中的finally子句。

11.  数组类型的值是对数组对象的引用,在java虚拟机中,数组是个真正的对象;而接口类型的值,则是对实现了该接口的某个实例的引用。还有一种特殊的引用值是null,它表示该引用变量没有任何引用对象。

12.  在java虚拟机中,负责查找并装载类型的那部分被称为类装载子系统。

13.  虚拟机必须为每个别装载的类型维护一个常量池。常量池就是该类型所有常量的一个有序集合,包括直接常量对其他类型、字段、方法的符号引用。

14.  在java程序中,你可以得到并使用指向class对象的引用。Class类中的一个静态方法可以让用户得到任何已经装载的类的Class的实例的引用。

Public static Class<?> forName(String className)

15.  所有具有相同维度和类型的数组都是同一个类的实例,而不管数组的长度是多少。

16.  Java的内存模型分为:Yong(年轻代)、Tenured(终身代)、Perm(永久代)

17.  注意Young(年轻代)可以分为Eden区和Survior区(from 和 to,这两个Survior区大小严格一致)。

18.  Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程。它主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用的上下文。栈空间随着线程的终止而释放。StackOverflowError:如果在线程执行的过程中,栈空间不够用,那么JVM就会抛出次异常,这种情况一般是死递归造成的。

19.  Yong区被划分为三个部分,Eden区和两个大小严格相同的Survivor区,其中Survivor区间中,某一时刻只有其中一个被使用的,另一个留作垃圾收集时复制对象用,在Young区间变满的时候,minor GC就会将存活的对象移动空闲的Survivor的区间中。

20.  Young=eden + 2*survivor

21.  –Xmn 参数设置了年轻代的大小 

22.  –XX:Xss 这线程栈大小

23.  Java语言是目前使用最多的依赖于垃圾收集器的语言,但是垃圾收集器策略从20世纪60年代就已经流行起来了,比如Smalltalk,Eiffel等变成语言也继承了垃圾收集器的机制。

24.  在java中,某个对象对应用程序时可达的是指:这个对象被根引用或者对象被另一个可到达的对象引用。

25.  垃圾收集策略:

1.      引用计数

a)        优点:简单直接,不需要暂停整个应用。

b)        缺点:需要编译器配合、不能处理循环引用的问题。

2.      跟踪收集器

跟踪收集器首先要暂停整个应用程序,然后开始从根对象扫描整个堆,判断扫描的对象是否有对象的引用,或者对对象的引用超出了作用域。

26.  GC在收集一个对象的时候会判断是否有引用指向对象,在java中的应用主要有四种:Strong reference,Soft reference, Weak reference, Phantom reference

27.  强引用是java中默认采用的一种方式,我们平时创建的引用都属于强引用。如果一个对象没有强引用,那么对象就会被回收。

28.  软引用的对象在GC的时候不会被回收,只有当内存不够用的时候才会真正的回收,因此软引用适合缓存的场合,这样使得缓存中的对象可以尽量的在内存中长久一点。

29.  弱引用有利于对象更快的被回收,假如一个对象没有强引用只有弱引用,那么在GC后,这个对象肯定会被回收。(可不可以理解为弱引用加速了对象的回收)

30.垃圾收集器

         (1)标记清除收集器

         (2)复制收集器

(3)标记整理收集器

31. GC的执行要耗费一定的CPU资源和时间的,因此在JDK1.2以后,JVM引入了分代收集策略,其中对新生代采用Mark-Compact策略,而对老生代采用了”Mark-Sweep” 的策略。其中新生代的垃圾收集器命名为”minor gc”,老生代的GC命名为Full GC或者Major GC” 其中用System.gc()强行执行的是Full GC。

32. G1收集器与CMS收集器相比由于两个显著的改进:一是G1收集器基于“标记-整理”算法实现的收集器,也就是说它不会产生空间碎片。二是它能非常精确的控制停顿,既能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。之前的收集器进行收集的范围都是整个新生代或者老年代,而G1将整个java堆(包括新生代、老年代)划分为多个大小固定的独立区域,并且跟踪这些区域里面的垃圾堆积程度,在后台维护一个优先级列表。

33.TLAB全称叫ThreadLocal Allocation Buffer, Sun JDK为了提高对象生成的效率,在Eden哪里为每一个创建的线程创造这么样的空间。TLAB的大小一般都是有JVM运行计算得出的,但是可以通过-XX:TLABWasteTargetPercent来设置TLAB可占用的Eden Space。在TLAB分配内存时不需要加锁,因为在堆上分配内存时要加锁,所以在TLAB分配时效率快很对。

34. 对象的内存分配,新生代主要在Eden区上,如果启动了本地线程缓冲,将线程优先在TLAB上分配。少数情况下也可能会直接分配在老年代中,分配规则并不是百分之百固定的,器细节取决于当前使用的是哪一种垃圾收集器的组合。

35. 普遍的内存分配规则:

         大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。

         虚拟机提供了-XX:+PrintGCDetails这个收集器日志参数,告诉虚拟机在发生垃圾收集行为时打印内存回收日志,并且在进程退出的时候打输出当前各区域的分配情况。

36. 新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为java对象大多数都具备朝生夕灭的特性,所以Minor GC 非常频繁,一般回收速度也比较快。

老年代GC(Magjor GC/Full GC):指发生在老年代GC,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对)。MajorGC 的速度一般会比Minor GC慢10倍以上。

 

37. 内存分配的原则:

         a)对象优先在Eden上分配

         b)大对象直接进入老年代

                  所谓大对象是指需要大量连续内存空间的java对象。大对象对内存分配来说是个坏消息,有可能提前出发垃圾回收以获得连续的内存空间。虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代中分配。

         c)长期存活的对象将进入老年代

38.虚拟机给每个对象定义了一个对象年龄计数器,如果对象在Eden出生并经过一次MinorGC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并将对象年龄设为1,对象在Survivor区中没熬过一次MinorGC,年龄就增加一岁,当它的年龄增加到一定程度(默认为15岁)时,就会被晋升到老年代中。对象晋升到老年代的年龄阀值,可以通过参数-XX:MaxTenuringThreshold来设置。

39. 如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或者等于该年龄的对象就可以直接进入老年代,无需等到MaxTenuringThreshold中要求的年龄。

40. 方法区存放了要加载的类信息,静态变量,final类型的变量,属性和方法信息。JVM用持久代(PermanentGeneration)来存放方法区,可以通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值。介绍完了JVM内存组成结构。

41. JVM内存结构可以分为:堆、栈、本地方法栈、方法区。

42.新生代采用空闲指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发GC。

43.并不是内存被耗空的时候才会抛出OutOfMemeoryException,满足一下两个条件时也会抛出:JVM98%的时间都花费在内存回收,每次回收内存小于2%。

满足这两个条件将触发OutOfMemoryException,这将会留给系统一个微小的间隙来做一些Down之前的操作,比如打印Heap Dump。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值