9、几种垃圾收集器:
#Serial收集器,stop the world,主要新生代,简单高效(单线程)
#ParNew收集器,基本是Serial的多线程版本。
#Paraller Scavenge收集器,新生代收集器,复制算法,并行多线程收集器。吞吐量优先。
#Serial Old收集器,Serial老年代版本,单线程。标记-整理算法。
#Parallel Old收集器,Parallel Scavenge的老年代版本,多线程,标记-整理
#CMS(Concurrent Mark Sweep)收集器,是一种获取最短回收停顿时间为目标的收集器。常用于互联网站或者bs系统,这类应用重视相应速度。标记-清除算法实现。
缺点:
1):对cpu资源非常敏感,即导致渣农cpu资源导致应用程序变慢
2):CMS收集器无法处理浮动垃圾(Floating Garbage),导致concurrent mode failure而导致另一次gc
3):基于“标记清除”,有大量碎片,从而难以分配内存给大对象。
#G1(Garbage-First)收集器:一款面向服务端应用的垃圾收集器,将来可能替代CMS收集器。具有如下特点:
1):并行与并发;
2):分代收集;
3):空间整合:在整体来看,g1基于标记整理算法,从局部来看(两个region之间)基于复制算法。因此不会产生空间碎片
4):可预见停顿:可以建立可预测的停顿时间模型
10、G1收集器:在g1之前的其他收集器,都是分新生代和老年代的,g1中java堆的内存布局就和其他的有很大差别,将整个java对分为多个大小相等的独立区域,虽然还保留新
生代和老年代的概念,但新生代和老年代不再是物理隔离了。
1):g1这种使用region划分内存空间以及有优先级的区域回收方式,保证了g1收集器在优先时间内可以获取更高的效率。
2):g1的运行大致可以划分为以下几个步骤:
#初始标记(Initial Marking)
#并发标记(Concurrent Marking)
#最终标记(Final Marking)
#筛选回收(Live Data Counting and Evacuation)
11、内存回收策略
1):新生代gc(Minor GC):指在新生代的垃圾收集动作,因此这里java对象大部分朝生夕灭,所以Minor GC很频繁
老年代gc(Major GC/ Full GC):指主要发生在老年代的gc,经常会伴随至少一次的Minor GC,但不确定,Major GC的速度一般会比Minor GC半10倍以上。
2):大对象直接进入老年代,大对象主要是指那些很长字符串以及数组,大对象对内存分配是一个坏消息,比这个还要坏的消息就是一个“朝生夕灭”的大对象,应该
避免使用这样的对象。
12、jvm处理工具:命令行
1):如果需要监控jdk1.5的虚拟机之上的程序,在程序启动时请添加参数“-Dcom.sun.management.jmxremote”开启jmx管理功能。
2):sun jdk监控和故障处理工具。
#jps JVM Process Status Tool,显示指定系统内所有的hotspot虚拟机进程
-q:指数出lvmid,省略主类的名称
-m:输出虚拟机启动时候传递给住类main()函数的参数
-l:输出主类的全名,如果进程执行的是jar包,输出jar路径
-v:输出虚拟机进程时jvm参数
root@anLA7856:/usr/java/jdk1.8/bin# jps -q
4768
4204
root@anLA7856:/usr/java/jdk1.8/bin# jps -m
4204 org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar -os linux -ws gtk -arch x86_64 -showsplash /usr/eclipse//plugins/org.eclipse.platform_4.4.2.v20150204-1700/splash.bmp -launcher /usr/eclipse/eclipse -name Eclipse --launcher.library /usr/eclipse//plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.1.200.v20150204-1316/eclipse_1607.so -startup /usr/eclipse//plugins/org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar --launcher.appendVmargs -exitdata dd8017 -product org.eclipse.epp.package.jee.product -vm /usr/bin/java -vmargs -Dosgi.requiredJavaVersion=1.6 -XX:MaxPermSize=256m -Xms40m -Xmx512m -jar /usr/eclipse//plugins/org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar
4783 Jps -m
root@anLA7856:/usr/java/jdk1.8/bin# jps -l
4204 /usr/eclipse//plugins/org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar
4798 sun.tools.jps.Jps
root@anLA7856:/usr/java/jdk1.8/bin# jps -v
4204 org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar -Dosgi.requiredJavaVersion=1.6 -XX:MaxPermSize=256m -Xms40m -Xmx512m
4813 Jps -Denv.class.path=/usr/java/jdk1.8/lib/ -Dapplication.home=/usr/lib/jvm/java-8-openjdk-amd64 -Xms8m
root@anLA7856:/usr/java/jdk1.8/bin# jps
4204 org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar
4828 Jps
#jstat JVM Statistics Monitoring Tool,用于手机hotspot虚拟机个方面的运行数据
用法:jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
option:主要3类,类加载,垃圾回收,运行时编译。
root@anLA7856:/usr/java/jdk1.8/bin# jstat -gcutil 4204
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 1.09 54.99 91.09 80.74 44 0.488 29 6.983 7.471
查询结果表明:本机,新生代Eden区(E,表示Eden),使用了1.09%空间,两个Survivor区(S0,和S1表示Survivor0和Survicor1)里面都是空的
老年代(O,Old)和永久代(P,permanent)则分别使用了54.99%和91.09。程序运行功法生Minor GC(YGC,Young GC)44词,总勇士0.488s,发生Full GC
29次,用时6.983s,所有gc耗时7.471s。
#jinfo Cconfiguration Info for Java ,显示虚拟机配置信息
root@anLA7856:/usr/java/jdk1.8/bin# jinfo -flag CMSInitiatingOccupancyFraction 4204
-XX:CMSInitiatingOccupancyFraction=-1
说明没有设置这个值。
#jmap Memory Map for Java,生成虚拟机的内存转储快照,(heapdump文件)
#jhat JVM Heap Dump Browser,用于分析headdump文件,它会简历一个http服务器,让用户可以在浏览器上查看分析结果。
#jstack Stack Trace for java,显示虚拟机线程快照
-F:当正常输出的请求不被相应时,强制输出线程堆栈
-l:除堆栈外,显示锁的附加信息
-m:如果调用本地方法外,可以显示c/c++的堆栈。
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server)
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
13、jdk的可视化工具。
1):jconsole,bin目录下面有。
2):VisualVM:基于netbeans开发,因此它具有插件功能。
#显示虚拟机进程以及进程配置、环境信息(jinfo、jps)
#监视应用程序的cpu、gc、堆、方法区以及线程。
#dump以及分析堆转储快照
#方法级的程序运行性能分析,找出被调用方法,运行时间最长的方法。
14、类文件结构相关:代码编译的结果是从本地及其码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步。
1):java虚拟机提供的语言无关性,例如,java(JRuby)程序通过javac(jrubyc)编译器,最终得到字节码(*.class)并且有java虚拟机执行。
2):魔数代表着其jdk的版本,,一般java class文件第一个是CAFEBABE,紧随其后就是jdk版本。p165有class文件格式表格。
15、在java中,重载要求有一个与原方法不同的特征签名,特征签名就是一个方法中各个参数在常量池中字段符号引用的集合,也就是返回值并不会包含在特征签名中,
所以无法使用返回值来对方法进行重载,但是在class文件中,两个方法有相同的名称和特征签名,但返回值不同,也是可以合法共存于一个class文件的。
16、虚拟机规范中明确限制了一个方法不允许超过65535条字节码指令,如果超过这个限制javac会拒绝编译。一般在java代码中很少会遇到,而在jsp中则可能遇到。
17、对于this关键字,仅仅是通过javac编译器编译的时候把对this关键字的访问转变为对一个普通方法参数的访问。
18、与数据类型相关的字节码指令,l代表long,s代表short,b代表byte,c代表char,f代表float,d代表double,a代表reference。
19、Tload一般是指将一个局部变量加载到操作栈,Tstore指令则是从操作数栈存储到局部变量表,将一个常量加载到操作数栈Tpush,或者Tconst。
将操作数栈的值存储到数组元素的指令:Tastore
20、jvm中运算指令:
加法指令:Tadd
减法指令:Tsub
乘法指令:Tmul
除法指令:Tdiv
求余指令:Trem
取反指令:Tneg
位移指令:Tshl或者Tshr
按位或指令:Tor
按位与指令:Tand
按位异或指令:Txor
局部变量自增指令:Tinc
比较指令:Tcmpg
21、在java虚拟机中,处理异常是由异常表来实现的,而不是字节码。
22、java虚拟机可以支持方法级同步和方法内部同步一段指令虚捏,都是使用管程(MOnitor)来实现的。
1):方法的同步是隐式的,当方法调用是,如果ACC_SYNCHRONIZED访问标志被设置了,就必须要求先获得管程,然后才能执行方法,最后执行完后释放管程。
管程只能在一个线程手上,发生异常则自动释放管程。
2):同步块则是有monitorenter和monitorexit两条指令来实现synchronized关键字来实现的,正确实现synchronized关键字需要javac编译器与java虚拟机两者
共同协作支持。为了保证monitorenter和monitorexit正常执行,编译器会自动产生一个异常处理器,这个异常处理器可处理所有异常,目的就是来执行
monitorexit指令。
23、class文件是java虚拟机执行引擎的数据入口。
24、在java语言里面,类型的加载,连接和初始化过程都是在程序运行期间完成的。
类从被加载到虚拟机内存开始,到卸载出内存为止,声明周期包括:
1):加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading)。
其中,验证,准备,和解析统称为连接。解析这一步骤某些情况下可以在初始化之后在进行,因为为了支持java语言的运行时绑定。
25、虚拟机规范中严格规定有且只有5中情况必须进行类初始化,即类加载。
1):遇到new(实例化对象)
遇到getstatic,putstatic(读取或这只一个类的静态字段,(被final修饰、已在编译器把结果放入常量池的静态字段除外))
遇到invokestatic(调用一个类的静态方法)
2):使用java.lang.reflect包方法,如果没有初始化。
3):当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类初始化。
4):虚拟机启动时,用户需要指定一个要执行的主类(包含main方法),虚拟机会初始化这个主类。
5):当使用jdk1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,
并且这个方法所对应的类没有进行过初始化。