java虚拟机学习笔记二

时间:2022-06-20 21:16:11
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的方法句柄,
    并且这个方法所对应的类没有进行过初始化。