"In-depth understanding of the Java Virtual Machine: JVM advanced features and best practices" study notes JAVA JPS command Detailed JVM tuning command -jmap memory problems and SWAP

The first part went into Java

First, walked into Java

1 Overview

  java is widely used in embedded systems, mobile terminals, enterprise servers, mainframes and other occasions, free from the shackles of hardware platforms, to achieve the "write once, run anywhere" ideal

2, java Technical Architecture

  Divided by function

  1. It includes the following components: Java programming language, a variety of hardware platforms java virtual machine, Java API class libraries, Java class libraries from third-party businesses and the open source community, Class File Format
  2. Java programming language, java virtual machine, Java API class libraries collectively referred to as JDK, java program is used to support the development of a minimal environment
  3. Java SE API subset of the Java API class libraries and Java Virtual Machine collectively referred to as JRE, support java program running basic environment

  According to the field of technology and services divided into four platforms

  1. Java Card: support java applets to run on the java platform small memory devices (such as smart cards) of
  2. Java ME: support the Java platform running on mobile devices
  3. Java SE: support for desktop applications platform
  4. Java EE: supports the use of multi-tiered enterprise applications platform

The second part of the automatic memory management

Second, the area of ​​memory and memory overflow exception

1, run-time data area

  Program Counter

  • Recording address of the virtual machine is a bytecode instruction being executed, the line number can be seen as an indicator bytecode currently executing thread, each thread has a separate program counter, a program counter thread pieces independently of each other, isolated storage, these memory areas become a "thread-private memory."
  • This memory area is not the only area in the case of OutOfMemoryError Virtual Machine Specification

  Java Virtual Machine stack

  • With the program counter, just as a thread private. Each method creates a stack frame at the time of execution, the local variable table for storing information, the operand stack, dynamic link, the method exports.
  • Each method execution until the call is completed, the process corresponds to a stack frame is pushed and popped in a virtual machine stack.
  • Required for completion of the local variable table memory space assigned during compilation, when entering a method, this method requires much space for local variables allocated in the stack frame is fully determined during operation of the method does not change the size of the local variable table .
  • If the stack depth virtual machine lock requests exceeds the allowable depth, StackOverFlowError will throw an exception. If the application can not expand enough memory, it will throw an OutOfMemoryError.

  Native method stacks

  • For the native method used by the virtual machine services, and virtual machines stack as native method stacks and an OutOfMemoryError will be thrown StackOverFlowError.

  Java heap

  • Java heap is shared by all threads of an area of ​​memory used to store an object instance, almost all object instances are assigned here.
  • Java heap is the main area of ​​garbage collection, using generational collection algorithm.
  • Java heap into the new generation and the old era, the new generation in more carefully into Eden, From Survivor, To Survivor space.
  • If you can not complete the heap memory allocated object instance, and the heap can not be extended, it will throw an OutOfMemoryError.

  Methods district

  • Each thread is a shared memory area for storing such information has been loaded virtual machine, constants, static variables, the time compiler to compile the code and other data, HotSpot virtual machine's design team to GC generational collection extends to the method area , or instead substituting permanent method area.
  • In the JDK1.7 HotSpot has been released, it has been originally placed in the permanent generation removed from the string constant pool. When the method area can not meet demand for memory allocation, it will throw an OutOfMemoryError.

  Runtime constant pool

  • The method is part of the region, Class file versions in addition to the classes, fields, methods, and interface description information, as well as a constant pool information, and for storing various literal reference symbol generated by the compiler, this part the method of operation will enter the region after the class loading time constant storage pool.
  • With respect to the runtime constant pool Class file constant pool, dynamic, during operation of the new constant may be placed in the constant pool, such as intern () method of class String.
  • When the runtime constant pool can not apply to more memory, it will throw an OutOfMemoryError.

  Direct Memory

  • Part of a region is not running, JDK 1.4 NIO added Native libraries can use it directly outside the allocated heap memory, and is operated by an object in the Java heap DirectByteBuffer this memory as a reference.

2, HotSpot virtual machine object Quest

  Creating objects

  • When faced with new instructions, to determine whether the class is loaded, parsed, initialized, if not, perform the loading process of the corresponding class.
  • After checked by loading class, the memory for the new object allocation, if regular Java heap memory is continuous, a "pointer collisions" distribution, if it is not continuous structured, a "free list" distribution. Memory depends on whether the regular garbage collector with or without compression sorting function.
  • Serial, ParNew with other collectors Compact process, the allocation algorithm "pointer collisions." And this CMS-based collector Mark-Sweep algorithm, usually a "free list" of distribution.
  • Involves allocating memory to create an object and a pointer to the two operations are not atomic, not thread safe. To address this issue, there are two solutions: one is the use of CAS plus failure retry to guarantee atomic operations. 2 is the use of TLAB (Thread Local Allocation Buffer) strategy, a small piece of pre-allocated heap memory for each thread, called TLAB (Thread Local Allocation Buffer) in Java, which thread to allocate memory is carried out in their respective memory TLAB only when assigned, only TLAB run a new distribution TLAB need genlock, whether to use virtual machine TLAB, by -XX: +/- UseTLAB
  • After the completion of memory allocation, you need to head to the object settings, including which this object is an instance of the class, how to find information such as metadata, hash code of the object, GC target sub-generation information age.
  • Finally, the init method to initialize the object in accordance with the wishes of the programmer. Such an object truly usable considered completely produced.

  Memory layout objects

  • Is divided into three regions, object header (Header), instance data (Instance Data), supplemented alignment (Padding).
  • Object header, the object storing runtime data itself, such as a hash code, the object of the GC generational age lock state flag bias thread ID, timestamp biased length which are part of the data in 32-bit and 64-bit virtual machine as 32bit and 64bit.
  • Another part is the type of pointer, the virtual machine is determined by the object which is an instance of the object class.

  Access the location of the object

  • Java program requires to specific objects in the heap by operation of reference data on the stack, embodied in two ways: direct pointer handle and use two kinds.
  • Use Handle: Java heap as memory is divided into a pool handle, the handle is stored in the address reference object handler includes a respective instance of data and the address information type data objects. The greatest benefit is that when an object changes, reference itself does not need to be modified because reference is stable in storage handler address

                                                    

  • Direct pointers: reference is stored directly address objects in the heap, the heap layout objects need to consider the type of data access information on how to place. The greatest benefit is faster and saves a pointer is positioned overhead, direct way HotSpot on the use of pointers.

                         

3, OutOfMemoryError abnormal

        Heap Overflow

  • Continue to create objects, ensure that a reachable route between GC Roots to object to avoid the garbage collection mechanism to remove these objects, reach the maximum heap size limit will produce memory overflow exception after.
  • -Xms20m minimum stack; -Xmx20m maximum stack; -XX: + when HeapDumpOnOutOfMemoryError Dump memory overflow exception dump the current snapshot memory heap for later analysis

        VM stack and native method stack overflow

  • -Xss stack capacity

        Methods and run constant pool overflow area

  • Multiple calls String.intern () method can produce memory overflow exception. Between JDK 1.6, by -XX: PermSize and -XX: MaxPermSize permanent restrictions on behalf size, thereby limiting the size of the object area method

        Local Direct Memory Overflow

  • By -XX: MaxDirectMemorySize specified. If not specified, the default and maximum Java heap (-Xmx specified) as

Third, garbage collection and memory allocation strategy

 1, the object is dead it? How to determine whether the object is still "alive"

  Reference counter method

  • Add a reference to an object counter, whenever a reference to its place, the counter is incremented when the reference fails, the counter is decremented.
  • The advantage is a simple determination, the efficiency is also high. The disadvantage is that the problem can not be solved mutually circular references

  Reachability analysis method

  • Through a series of objects referred to as "GC Roots" as a starting point, to start the search downward from these nodes, the search path traversed referred to as "reference chain", when an object is not connected to any reference GC Roots chain, the Description this object is recyclable.
  • Java language can be used as GC Roots objects include the following: objects in the virtual machine stack referenced methods zone class object static properties referenced object method constant reference area, the object JNI native method stack references.

   Talk about references

  • After the JDK1.2 references divided into four categories: strong references, soft references, weak references, phantom references
  • Strong Quote: As long as there are strong references, it will not be garbage collected. Similarly Object o = new Object ()
  • Soft Quote: refers to the number of useful but not essential object when the system is going to happen out of memory, which will be part of the object is reclaimed. SoftReference classes to implement soft references
  • Weak references: the weak reference objects associated only survive until the next garbage collection. WeakReference classes to implement weak references
  • Phantom reference: whether there is a virtual object has cited, will not affect their survival repairer, made reference to the object can not be referenced by the virtual. A reference object setting virtual sole purpose is to receive a notification when the system is recovered waste

   Recovery process object

  • When the object reachability analysis does not refer to the GC Roots connected to the chain, it will be the first mark, and a screened according to whether you need to perform finalize () method, the object does not override finalize () or the virtual machine has been called finalize (), it is considered necessary to perform
  •  If the object is necessary to perform finalize, will be put to the F-Queue queue and low priority thread later Finalizer automatically created by the virtual machine to trigger it, does not guarantee the end of the wait for this method is executed.
  • If the object in the finalize () method execution, and re-GC Roots produced a chain of references, you can escape the fate of being recycled, but finalize () method is run only once, so the next time it was recovered by this method can not escape
  • I do not recommend using this method, we suggest that you completely forget about the existence of this approach.

   Recovery process area

  • Including waste and recycling unwanted constants class. Analyzing useless categories: class instance is recovered, recovered ClassLoader class, object class java.lang.Class not referenced anywhere. Three conditions are satisfied, the class can be recovered (unloaded)
  •  HotSpot virtual machine control is enabled by -Xnoclassgc class uninstall feature parameters. In the use of a large number of reflective, dynamic proxies, CGLib other frame, the virtual machine includes a class needs to unload function, the method to avoid memory overflow region

2, garbage collection algorithm

  Mark - Clear

  • First mark all objects to be recovered, unified recovered after labeling the object is complete. There are two problems:

       1 is an efficiency issue, mark and sweep efficiency is not high.

       2 is a space problem, it will produce a large number of discrete memory fragmentation, fragmentation too much can lead to large objects are unable to find enough memory, triggering garbage collection from the advance.

  Replication algorithm

  • Eden is divided into a new generation, two Survival space, the default ratio is 8: 1. When recycling, the Eden and survival object Survival Survival of all fit into another space, and finally just clean out of Eden space and Survival
  •  When Survival is not enough space, memory allocation guaranteed by years old

  Mark - finishing

  • According to the characteristics of the object's old, marking the first live objects, live objects will move to the end, and then directly to clean out the object other than the end border

  Generational collection

  • The use of the new generation of replication algorithm, using old's mark - delete, or mark - sorting algorithms.

3, HotSpot algorithm

  Enumeration root achieve

  • GC pauses will be when reachability analysis, stop all Java threads.
  • HotSpot is carried out accurately type GC, when the system to a halt, there are ways to know which virtual machine where there is an object reference, use a group called HotSpot OopMap data structures to achieve this objective

  Security point

  • HotSpot are not generated for each instruction OopMap, only the information recorded in a particular position, which position is referred to a safe point. Selected safety point of not too little, not too often, the selected security point of "whether to allow the implementation of the program for a long time" as the standard
  • The use of active interrupt way to make all the threads have come to a halt on the nearest safe point. A flag is set, program execution time of each poll this flag, found the interrupt flag is true and that they interrupt pending

  Security Zone

  • Temporary settlement procedure is not performed is not assigned Cpu time to pause.

4, the garbage collector

              If there is connection between two collectors, it can be explained with the use. Not the best collector, no universal collector, only the most appropriate application corresponds to a specific collector.

Serial Collector

  • New generation collector, threaded recovered. Advantageously, simply and efficiently, in a virtual machine for running the Client mode it is a good choice (such as the user's desktop application)
  • Parameters -XX: UseSerialGC, this switch is open, Serial + collector using a combination of memory is recovered Serial Old

  ParNew collector

  • The new generation of collectors, Serial multi-threaded version, in addition to Serial collector, it only works with CMS collector.
  • -XX: + UseConcMarkSweepGC default option after the new generation of collectors, you can also use the -XX: + UseParNewGC option to force it to specify
  • ParNew collected in a single-CPU environment, the effect is not as good as Serial, with the increase in CPU, for the use of system resources when GC is still very effective.
  • Collection enabled by default equal number of threads and the number of CPU, you can use -XX: ParallelGCThreads specified

  Parallel Scavenge collector

  • The new generation of collectors, parallel collector, different replication algorithm, and other collectors, the focus is the throughput (garbage collection time percentage of time spent). It provides two parameters for controlling the throughput.
  • -XX: MaxGCPauseMillis, the largest garbage collection pause time, reduce the GC pause time at the expense of throughput and space in exchange for the new generation, not set as small as possible
  • -XX: GCTimeRatio, provided certain size range of less than 100 that is greater than a value of 0, corresponds to the reciprocal of the throughput, such as 99 is arranged, the throughput of 1 / (1 + 99) = 1%.
  • -XX: UseAdaptiveSizePolicy, which is a switch parameter, after opening, there is no need to set the size of the new generation (-Xmn), Eden and Survival ratio (-XX: SurvivalRatio), promoted's old target age (-XX: PretenureSizeThreshold), etc. details of parameters, the collector will automatically adjust these parameters.

  Serial Old collectors

  • 单线程收集器,老年代,主要意义是在Client模式下的虚拟机使用。在Server端,用于在JDK1.5以及之前版本和Parallel Scavenge配合使用,或者作为CMS的后备预案。

  Palallel Old 收集器

  • 是Parallel Scavenge的老年代版本。在注重吞吐量的场合,都可以优先考虑Parallel Scavenge 和Palallel Old 配合使用

  CMS 收集器

  • Concurrent Mark Sweep,是一种以获取最短回收停顿时间为目标的收集器,尤其重视服务的响应速度。基于标记-清除算法实现。
  • 分为四个步骤进行垃圾回收:初始标记,并发标记,重新标记,并发清除。只有初始标记和重新标记需要停顿。
  • 初始标记只是标记一下GC Roots能直接关联到的对象,速度很快。并发标记就是进行GC Roots的Tracing。
  • 重新标记为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间会比初始标记阶段稍长,远比并发时间短。
  • 耗时最长的并发标记和并发清除过程中,处理器可以与用户线程一起工作。
  • 它并不是完美的,有如下三个比较明显的缺点:

     1、垃圾回收时会占用一部分线程,导致系统变慢,总吞吐量会降低。

     2、无法处理浮动垃圾,需要预留足够的内存空间给用户线程使用,可以通过 -XX:CMSInitiatingOccupancyFraction 参数控制触发垃圾回收的阈值。

       如果预留的内存无法满足程序需要,就会出现“Concurrent Mode Failure”失败,这时将启动应急预案,启用Serial Old 进行垃圾回收,停顿时间会变长

       所以-XX:CMSInitiatingOccupancyFraction 参数的值设置的太高,会导致频繁“Concurrent Mode Failure”失败,性能反而降低。

     3、标记-清理,容易产生内存碎片。-XX:+UseCMSCompactAtFullColletion 开启碎片整理功能,默认开启,-XX:CMSFullGCsBeforeCompaction,控制多少次不压缩的FullGC之后来一次带压缩的

  G1 收集器

  • 包括新生代和老年代的垃圾回收。和其他收集器相比的优点:并行和并发,分代收集,标记-整理,可预测的停顿。垃圾回收分为以下几个步骤:
  • 初始标记:标记GC Roots能够直接关联到的对象,这阶段需要停顿线程,时间很短
  • 并发标记:进行可达性分析,这阶段耗时较长,可与用户程序并发执行
  • 最终标记:修正发生变化的记录,需要停顿线程,但是可并行执行
  • 筛选回收:对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来执行回收计划

5、内存分配和回收策略

  • 对象优先在Eden分配,当新生区没有足够的内存是,通过分配担保机制提前转移到老年代中去
  • 大对象直接进入老年代。大对象是指需要大量连续内存空间的对象,虚拟机提供了参数 -XX:PretenureSizeThreshold(只对Serial,PerNew两个回收器起效),令大于这个值得对象直接在老年代分配,避免了Eden和两个Survival之间发生大量的内存复制。
  • 长期存活的对象将进入老年代。虚拟机给每个对象定义了对象年龄计数器(Age),如果对象在Eden出生,经过第一次Minor GC后依然存活,并且能被Survival容纳的话,将被移动到Survival,对象年龄设为1。对象在Survival中每熬过一次Major GC,年龄就增加1,达到一定程度(默认是15),就会被晋升到老年代。对象晋升老年代的阈值,可以通过参数-XX:MaxTenuringThreShold 指定
  • 动态对象年龄判断。如果在Survival空间中相同年龄所有对象的大小综合超过了Survival空间的一半,年龄大于等于这个年龄的对象都会被晋升到老年代。无需等待年龄超过MaxTenuringThreShold指定的年龄
  • 空间分配担保。只要老年代的连续空间大于新生代对象总和或者历次晋升的平均大小,就进行Major GC,否则进行Full  GC。

四、虚拟机性能监控与故障处理工具

1、jps

命令用法: jps [options] [hostid]

功能描述: jps是用于查看有权访问的hotspot虚拟机的进程. 当未指定hostid时,默认查看本机jvm进程

常用参数:-lmvV

详细说明:JAVA JPS 命令详解

2、jstat。监视JVM内存工具。

语法结构:

Usage: jstat -help|-options

       jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

例子: jstat -gcutil 25444 1000 5

详细说明:JDK之jstat的用法

3、jinfo。查看和修改JVM运行参数

java -XX:+PrintFlagsFinal -version|grep manageable    【查看JVM中哪些参数可以被jinfo动态修改】

 jinfo -flag +PrintGCDetails 105704    【修改参数 PrintGCDetails 的值】

4、jmap。命令用于生成heap dump文件

如果不使用这个命令,还可以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM的时候自动生成dump文件。

 jmap不仅能生成dump文件,还可以查询finalize执行队列、Java堆和永久代的详细信息,如当前使用率、当前使用的是哪种收集器等。

详细使用:JVM调优命令-jmap

5、jstack。Java堆栈跟踪工具

详细使用:使用jstack精确找到异常代码jstack 工具使用性能调优

注意:dead lock问题,占用cpu时间最多的线程,频繁GC

入手点总结:

wait on monitor entry: 被阻塞的,肯定有问题,等待synchronized锁

runnable : 注意IO线程,IO阻塞的线程

in Object.wait(): 注意非线程池等待,调用Object.wait()的对象

五、常见JVM配置说明

1、JVM配置

1.1、G1

CPU 核数:8;内存(GB):16;磁盘(GB):400

-Xms10g

-Xmx10g

-Xss512k

-XX:MetaspaceSize=256m

-XX:MaxMetaspaceSize=256m

-XX:MaxDirectMemorySize=128M
-XX:+UseG1GC

-XX:MaxGCPauseMillis=150

-XX:+ParallelRefProcEnabled

-XX:+UnlockExperimentalVMOptions

-XX:G1MaxNewSizePercent=70

-XX:ParallelGCThreads=8

-XX:ConcGCThreads=2

1.2、CMS+ParNew

CPU 核数:4;内存(GB):8;磁盘(GB):200

-Xmx4g
-Xms4g
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=256m
-XX:SurvivorRatio=8
-XX:NewRatio=4
-XX:+HeapDumpOnOutOfMemoryError
-XX:+DisableExplicitGC
-XX:+PrintGCDetails
-XX:+UseConcMarkSweepGC
-XX:ParallelGCThreads=4
-XX:+CMSClassUnloadingEnabled
-XX:CMSFullGCsBeforeCompaction=1
-XX:CMSInitiatingOccupancyFraction=72

1.3、参数说明

通用参数

参数

介绍

-Xms10g

-Xmx10g

-Xms10g , 初始化堆大小。通常情况和-Xmx大小设置一样,避免虚拟机频繁自动计算后调整堆大小。 
-Xmx10g ,最大堆大小。

-XX:MaxDirectMemorySize=128M

本地直接内存大小。适合频繁的IO操作,例如网络并发场景(NIO)

直接内存和堆内存比较:

  • 直接内存申请空间耗费更高的性能,当频繁申请到一定量时尤为明显

  • 直接内存IO读写的性能要优于普通的堆内存,在多次读写操作的情况下差异明显

-XX:+PrintGCApplicationStoppedTime

打印垃圾回收期间程序暂停的时间 

-XX:+PrintGC

打印GC基本日志 

-XX:+PrintGCDetails

打印GC详细日志 

-XX:+DisableExplicitGC

关闭System.gc()

-Xss512k

每个线程堆栈大小。每一次方法的调用都对应一个入栈和出栈

-XX:PermSize=256m

-XX:MaxPermSize=256m

-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=256m

JDK8以前:

  • 永久代初始值

  • 永久代最大值

JDK8及以后:

  • 原空间初始值

  • 原空间最大值

-XX:+HeapDumpOnOutOfMemoryError

JVM异常自动生成堆转储

CMS

参数

说明

-XX:+UserConcMarkSweepGC

年老代指定CMS垃圾回收器,新生代默认用ParNew收集

-XX:ParallelGCThreads=4

设置垃圾收集线程数

-XX:CMSInitiatingOccupancyFraction=72

老年代垃圾占比达到这个阈值开始CMS收集,设置过高容易导致并发收集失败,会出现SerialOld收集的情况

-XX:+UseCMSCompactAtFullCollection(默认开启,不需要设置)

在FULL GC的时候, 对年老代开启碎片整理功能,默认开启

-XX:CMSFullGCsBeforeCompaction=1

控制FullGC压缩的间隔。多少次不压缩的FullGC之后来一次带压缩的

-XX:+CMSClassUnloadingEnabled

CMS收集器默认不会对永久代进行垃圾回收。如果希望对永久代进行垃圾回收,可以设置标志

-XX:+CMSParallelRemarkEnabled

为了减少第二次暂停的时间,开启并行remark,降低标记停顿

-XX:NewRatio=4

新生代:老年代=1:4

-XX:SurvivorRatio=8

2个survivor和eden的比值。表示2:8

默认为8,也就是说Eden占新生代的8/10,From幸存区和To幸存区各占新生代的1/10

G1

参数

说明

-XX:+UseG1GC

使用G1垃圾回收

-XX:MaxGCPauseMillis=150

GC最大暂停时间

-XX:+ParallelRefProcEnabled

打开并行引用处理

-XX:+UnlockExperimentalVMOptions

有些时候当设置一个特定的JVM参数时,JVM会在输出“Unrecognized VM option”后终止。如果参数输入是正确的,并且JVM并不识别,需要设置-XX:+UnlockExperimentalVMOptions 来解锁参数。

-XX:G1NewSizePercent

新生代最小值比例。默认5%

-XX:G1MaxNewSizePercent=70

新生代最大值比例

-XX:ParallelGCThreads=8

STW期间,并行GC线程数

-XX:ConcGCThreads=2

并发标记阶段,并行执行的线程数

 

六、JVM调优案例分析与实践

1、Minor GC、Major GC和Full GC之间的区别

  • 每次 Minor GC 会清理年轻代的内存
  • Major GC 是清理老年代,Full GC 是清理整个堆空间—包括年轻代和老年代。大部分时候Major GC和Full GC区分的不是很明显
  • 不仅仅Major GC和Full GC会stop-the-world。所有的 Minor GC 都会触发“全世界的暂停(stop-the-world)”,停止应用程序的线程。对于大部分应用程序,停顿导致的延迟都是可以忽略不计的。其中的真相就 是,大部分 Eden 区中的对象都能被认为是垃圾,永远也不会被复制到 Survivor 区或者老年代空间。如果正好相反,Eden 区大部分新生对象不符合 GC 条件,Minor GC 执行时暂停的时间将会长很多。

2、常用命令

查看java进程号

两种方式都可以查看tomcat进程号
ps -ef | grep java

jps -lmvV |grep java

结果如下:2556

查看进程内线程情况
top -Hp 2556(2556为上一步查询出来的进程号)
找到占用cpu时间最长的线程号:3345

得到线程号的十六进制数
printf "%x\n" 3345(输出为a05)

使用jstack定位问题
jstack 2556 | grep a05

查看内存和swap使用情况。参考:https://www.cnblogs.com/coldplayerest/archive/2010/02/20/1669949.html

free -h   

 3、问题排查

内存和SWAP问题

七、虚拟机类加载机制

1、虚拟机把表示类的class文件加载到内存,经过校验、转换解析、初始化,最终形成可以被虚拟机直接使用的java类型,这就是虚拟机的类加载机制

2、类加载的时机

  • 使用new关键字实例化对象的时候、读取一个类的静态字段的时候、调用类的静态方法的时候
  • 使用java.lang.reflect包的方式对类进行反射调用的时候
  • 初始化类,发现其父类还未初始化,需要对父类进行初始化

3、类加载的过程

  • 加载。通过类的全限定名获取到定义此类的二进制字节流。将字节流所代表的静态存储结构转化成方法区的运行时数据结构。在方法区生成这个类的java.lang.Class对象。加载阶段和连接阶段的部分内容是交叉进行的。用户可以通过自己写的类加载器去控制字节流的获取方式(重写类加载器的loadClass()方法),
  • 验证。是连接阶段的第一步。目的是确保class文件中的二进制字节流符合虚拟机的要求,不会危及虚拟机自身安全。包括文件格式验证、元数据验证、字节码验证
  • 准备。是连接阶段的第二步。是正式为类变量分配内存空间和设置初始值的阶段。这个初始值和初始化阶段的赋值不同,这里指的是变量的默认初始值。另外,如果时final修饰的变量,那么会在准备阶段赋予代码里指定的初始值
  • 解析。是连接阶段的第三步。是虚拟机将符号引用替换为直接引用的过程
  • 初始化。根据程序代码去初始化类变量和其他资源

4、类加载器

  • 被不同类加载器加载的同名类,也认为是不同的类。
  • 双亲委派模型。分为两种类加载器: 1 是启动类加载器 ,是虚拟机自身的一部分;2 是所有的其他类加载器,这些类加载器都由java语言实现。独立于虚拟机外部,全部继承自java.lang.ClassLoader抽象类。类加载器具体层次关系:启动类加载器->扩展类加载器->系统类加载器->自定义类加载器。每一个类的加载,会优先由父加载器来加载。这种方式就称为双亲委派,双亲委派保证了java基本类的不会被破坏和替代

第五部分  高效并发

十二、Java内存模型与线程

 1、硬件的效率与一致性

  • 完成计算任务,处理器必须和内存交互才能完成,比如读取运算数据,写入计算结果等。这个I/O操作是很难消除的。计算的处理器和存储设备的运算速度有几个数量级的差距。所以现代计算机加入了一层读写速度尽可能接近处理器的高速缓存
  • 高速缓存解决了处理器和内存的速度矛盾,却引入了新的问题:内存一致性。多处理器系统中,各个处理器都有自己的高速缓存,又同时共用内存。为了解决这一问题,在读写内存时需要遵循缓存一致性协议
  • 处理器会对输入的代码进行乱序执行优化,类似的,Java虚拟机也存在着指令重排序优化。

2、Java内存模型

Java内存模型规定,所有的变量(这个变量和java编程中的变量有区别,它包括了实例字段、静态字段。不包括局部变量和方法参数,因为后者是线程私有的)都存储在主内存,每条线程有自己的工作内存,工作内存中保存了该线程使用到的变量的拷贝副本,线程对变量的所有操作都必须在工作内存中进行,线程间变量值得传递需通过主内存来完成

主内存和工作内存间交互协议,8种原子操作:

  • lock(锁定主内存)
  • unlock(解锁主内存)
  • read(读取主内存,为load准备)
  • load(载入主内存至工作内存)
  • use(执行引擎使用工作内存)
  • assign(接受执行引擎计算后的值赋值给工作内存)
  • store(存储工作内存至主内存,为write准备)
  • write(把工作内存写入主内存)

volatile是java虚拟机提供的轻量级的同步机制,对于volatile变量的特殊规则:

  • 保证了变量对所有线程的可见性,当一个线程修改了这个变量的值,修改后的值对其他线程来说是立即可见的。普通变量,需要通过把新值会写到主内存,其他线程从主内存读取之后才可以看到最新值
  • 禁止指令重排序优化。
  • 无法保证符合操作的原子性,比如i++
  • 通过内存屏障实现的可见性和禁止重排序。不同硬件实现内存屏障的方式不同,Java内存模型屏蔽了这些差异,由JVM来为不同的平台生成相应的机器码来完成。X86 处理器只会对写-读进行指令重排序,写volatile变量时,会加lock总线锁,将cpu缓存写入主存,其他cpu的读都会被阻塞,然后其他核的缓存某些对应数据会被标记为失效,那么其他核下次读的时候先读缓存发现失效了,然后去主存读

关于long和double类型变量的特殊规则:允许虚拟机将没有被volatile变量修饰的64位数据的读写操作划分为两次32位的操作来进行。这点就是long和double的非原子性协定

3、Java与线程

Java虚拟机实现线程,有三种方式:

(1)通过内核线程实现。jvm中的一个线程对应一个轻量级进程,一个轻量级进程对应一个内核线程。CPU通过调度器对线程进行调度。缺点:

  • 由于基于内核线程实现,各种线程操作需要系统调用,系统调用代价较高,需要在用户态和内核态之间来回切换
  • 每个线程都需要一个内核线程的支持,因此轻量级进程会消耗内核资源,一个系统支持的轻量级进程是有限的

(2)使用用户线程实现。不需要切换回内核态,也可以支持规模更大的线程数量。部分高性能数据库的多线程就是使用用户线程实现的。缺点是没有系统内核的支援,所有问题需要自己考虑,程序实现比较复杂

(3)内核线程和用户线程结合

(4)JVM,对于Sun JDK来说,在Windows和LInux系统下,都是使用的一对一的线程模型实现的。

Java线程调度

  • 协同式线程调度。线程的执行时间由自己控制,线程执行完毕,会主动通知系统
  • java使用的是抢占式调度。每个线程有系统分配执行时间,线程的切换也有系统来决定,线程的执行时间是可控的。线程可以设置优先级,来争取更多的执行时间。Java一共设置了10个优先级,操作系统的优先级数量可能和java定义的不一致,另外操作系统还可以更改线程的优先级,所以Java中优先级高的线程并不一定被优先执行。

Java线程状态转换

 

十三、线程安全与锁优化

高效并发是从jdk1.5 到jdk1.6的一个重要改进,HotSpot虚拟机开发团队耗费了大量的精力去实现锁优化技术

    • 自旋锁与自适应自旋。同步互斥对性能最大的影响就是线程挂起、恢复需要从用户态切换到内核态,切换的过程会造成系统消耗。往往锁定的代码段执行时间非常短,为了这个短的时间去挂起和恢复是不值得的。所以提出了自旋锁的概念,当线程申请获取一个其他线程占用的锁时,这个线程不会立即挂起,而是通过一定次数的循环自旋,这个过程不会释放cpu的控制权,自适应自旋就是根据上一次自旋的结果来决定这一次自旋的次数
    • 锁消除。虚拟机即时编译器在运行时会把检测到不可能发生共享数据竞争的锁消除
    • 锁粗化。一系列的操作都是对同一个对象的加锁和解锁,虚拟机检测到这种情况会将锁的范围扩大(粗化)
    • 轻量级锁
    • 偏向锁。如果程序中大多数的锁总是被多个线程访问,那偏向锁模式就是多余的。可以使用参数 -XX:-UseBiasedLocking来禁止偏向锁

Guess you like

Origin www.cnblogs.com/manmanchanglu/p/11618560.html