`
maosheng
  • 浏览: 550313 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JVM 深入剖析

    博客分类:
  • Java
jvm 
阅读更多
JVM是JAVA虚拟机(JAVA Virtual Machine)的缩写,是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JAVA虚拟机有自己完善的虚拟硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM屏蔽了与具体操作系统平台相关的信息,使得JAVA程序只需生成在JAVA虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。





JVM的生命周期:

(1) JVM 实例的诞生
当启动一个JAVA程序时,一个JVM实例就产生了,任何一个拥有public static void main(String[] args)函数的class都可以作为JVM实例运行的起点。

(2) JVM 实例的运行
main()作为该程序初始线程的起点,任何其他线程均由该线程启动。JVM内部有两种线程:守护线程和非守护线程,main()属于非守护线程,守护线程通常由JVM自己使用,JAVA程序也可以标明自己创建的线程是守护线程。

(3) JVM 实例的消亡
当程序中的所有非守护线程都终止时,JVM才退出;若安全管理器允许,程序也可以使用Runtime类或者System.exit()来退出。


JVM  :JAVA 虚拟机
所有的JAVA程序都是运行在JVM上,JVM是JRE的一部分。

JRE  : JAVA Runtime Environment(JAVA 运行环境)
JRE主要用于执行JAVA程序,JRE除了包含JVM外还包含一些基础的JAVA API,JRE是JDK的一部份。

JDK : JAVA Development Kit(JAVA 开发工具包)
JDK提供了JAVA的开发环境和运行环境(JRE),开发环境主要包含了一些开发工具,例如常用的JAVAc编译工具、jar打包执行程序、还有一些JVM监控工具等等。





JVM体系结构:

JVM 的结构基本上由四部分组成:
1.类加载器,在JVM启动时或者在类运行时将需要的Class加载到JVM中。
2.执行引擎,执行引擎的任务是负责执行Class文件中包含的字节码指令,相当于实际机器的CPU。
3.内存区,将内存划分成若干个区以模拟实际机器上的存储、记录和调度功能模块。
4.本地方法调用,调用C或C++实现的本地方法的代码返回结果。





JVM 体系结构主要包含两个子系统和两个组件:
Class Loader(类加载器)子系统,Execution Engine(执行引擎)子系统
Runtim Data Area(运行时数据区域)组件,Native Interface(本地接口)组件





Class Loader  类加载器:

类加载器负责加载 JAVA 类的字节代码到JAVA 虚拟机中,可以根据指定的类名(如java.lang.Object)来装载class文件的内容到Runtime data area中的method area(方法区域)。JAVA程序员可以extends java.lang.ClassLoader类来写自己的Class loader。




双亲委派模型工作过程
如果一个类加载器接收到了类加载的请求,它首先把这个请求委托给他的父类加载器去完成,每个层次的类加载器都是如此,因此所有的加载请求都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它在搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

优点:java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在tools.jar中,无论哪个类加载器要加载这个类,最终都会委派给启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果用户自己写了一个名为java.lang.Object的类,并放在程序的Classpath中,那系统中将会出现多个不同的Object类,java类型体系中最基础的行为也无法保证,应用程序也会变得一片混乱。


站在JVM的角度讲,主要有两种类型加载器:启动类加载器和所有其它的类加载器。

启动类加载器是JVM实现的一部分,使用C++语言实现,其它类加载器都由java语言实现 ,独立于虚拟机外部,并且全部继承抽象类java.lang.ClassLoader

(1) Bootstrap ClassLoader  启动类加载器
这是JVM的根ClassLoader,它是用C++实现的,JVM启动时初始化此ClassLoader,并由此ClassLoader完成$JAVA_HOME$中jre\lib\rt.jar(Sun JDK的实现)中所有class文件的加载,这个jar中包含了java规范定义的所有接口以及实现。启动类加载器无法被JAVA程序直接引用。

(2) Extension ClassLoader  扩展类加载器
扩展类加载器负责加载<JAVA_HOME>\lib\ext目录中或者java.ext.dirs系统变量所指定的所有类库,开发者可以直接使用扩展类加载器。

(3)Application ClassLoader  应用程序类加载器
JVM用此classloader来加载用户类路径 (Classpath)上所指定的类库,包含指定的jar包以及目录,该加载器有时也称为系统类加载器。开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

(4) User-Defined ClassLoader  用户自定义类加载器
User-DefinedClassLoader是Java开发人员继承ClassLoader抽象类自行实现的ClassLoader,基于自定义的ClassLoader可用于加载非Classpath中的jar以及目录。


类加载器之类加载过程:





1.  加载
加载过程负责找到二进制字节码并加载至JVM中,JVM通过类名、类所在的包名通过ClassLoader来完成类的加载。

在加载阶段,虚拟机需要完成以下三件事情:
1.通过一个类的全限定名来获取定义此类的二进制字节流
2.将这个字节流所代表的静态存储结构化为方法区的运行时数据结构
3.在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口

2.  连接
链接过程负责对二进制字节码的格式进行校验、初始化装载类中的静态变量以及解析类中调用的接口、类。
(1)验证:确保被导入类的正确性
(文件格式验证、数据验证、字节码验证、符号引用验证)

(2)准备:为类变量分配内存,并将其初始化为默认值
(准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配
首先是这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在Java堆中。

(3)解析:把类中的符号引用转换为直接引用
(解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。
直接引用可以是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。直接引用是与虚拟机实现的内存布局相关的
解析动作主要针对 类或接口、字段、类方法、接口方法四类符号引用进行。)

3. 初始化
初始化过程即为执行类中的静态初始化代码、构造器代码以及静态属性的初始化,在四种情况下初始化过程会被触发执行:调用了new;反射调用了类中的方法;子类调用了初始化;JVM启动过程中指定的初始化类。

JVM 加载类的阶段:




第一个阶段是找到.class文件并把这个文件包含的字节码加载到内存中。

第二个阶段又可以分为三个步骤,分别是字节码验证、Class类数据结构分析及相应的内存分配和最后的符号表的链接。

第三个阶段是类中静态属性和初始化赋值,以及静态块的执行等。


Execution Engine 执行引擎:

执行引擎是JVM最核心的组成部分之一,其主要是执行class中的指令,任何JVM实现的核心是Execution engine 。执行引擎可以把JAVA字节码转为机器能识别的字节码,并调用机器的指令进行计算等,不同JVM的执行效率很大程度决定于他们各自实现的Execution engine的好坏。“虚拟机”的执行引擎与“物理机”的执行引擎是比较类似的,这两种机器都有执行代码能力,其区别是物理机的执行引擎是直接建立在处理器、硬件、指令集和操作系统层面上的,而虚拟机的执行引擎是自己实现的,因此虚拟机可以自行制定指令集与执行引擎的结构体系,并且能够执行那些不被硬件直接支持的指令。

执行引擎也就是执行员一条条代码的一个流程,而代码都是包含在方法体内的,所以执行引擎本质上就是执行一个个方法所串起来的流程,对应到操作系统中一个执行流程就是一个Java线程。因为一个Java进程可以有多个同时执行的执行流程。这样说来每个Java线程就是一个执行引擎的实例,那么在一个JVM实例中就会同时有多个执行引擎在工作,这些执行引擎有的在执行用户的程序,有的在执行JVM内部的程序(如Java垃圾收集器)

每当创建一个新的线程时,JVM会为这个线程创建一个Java栈,同时会为这个线程分配一个PC寄存器,并且这个PC寄存器会指向这个线程的第一行可执行代码。每当调用一个新方法时会在这个栈上创建一个新的帧数据结构,这个栈帧会保留这个方法的一些元信息,比如这个方法中定义的局部变量、一些用来支持常量池的解析、正常方法返回及异常处理机制等。


Java执行部件:





JAVA Native Interface(JNI)本地接口:
Java本地接口(Java Native Interface,JNI)是一个标准的Java API,它支持将 Java 代码与使用其他编程语言编写的代码相集成,例如可以调用Native语言函数C\C++等。JNI是java与其它编程语言交互的接口。

Runtime Date Area 运行时数据区:
这个组件就是JVM的内存区域。

Runtime data area  主要包括五个部分:
Heap ( 堆)
Method Area( 方法区域)
VM Stack( 虚拟机栈 )
Native method stack( 本地方法栈)
Program Counter( 程序计数器)

Heap 和 Method Area是被所有线程的共享使用的;而vm stack, Program counter 和Native method stack是以线程为粒度的,每个线程独自拥有 。


1.程序计数器Program Counter Register:

程序计数器是是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器完成。JAVA虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程”私有的内存。

2.虚拟机栈 VM stack:

与程序计数据器一样,JAVA虚拟机栈也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是JAVA方法执行的内存模型:JAVA 栈总是和线程关联在一起的,每当创建一个线程时,JVM就会为这个线程创建一个对应的Java栈,在这个Java栈中又会包含多个栈帧(Stack Frame),每个方法被执行时都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入到出栈的过程 。

每当一个方法执行完成时,这个栈帧就会弹出栈帧的元素作为这个方法的返回值,并清除这个栈帧,Java栈的栈顶的栈帧就是当前正在执行的活动栈,也就是当前正在执行的方法,PC寄存器也会指向这个地址。只有这个活动的栈帧的本地变量可以被操作栈使用,当在这个栈帧中调用另外一个方法时,与之对应的一个新的栈帧又被创建,这个新创建的栈帧又被放到Java栈的顶部,变为当前的活动栈帧。同样现在只有这个栈帧的本地变量可能被使用,当在这个栈帧中所有指令执行完成时这个栈帧移出Java栈,刚才的那个栈帧又变为活动栈帧,前面的栈帧的返回值又变为这个栈帧的操作栈中的一个操作数。如果前面的栈帧没有返回值,那么当前的栈帧的操作栈的操作数没有变化。

VM Stack:java的线程栈,java分配一个对象时,对象的具体内容在堆中,而对象的引用则位于栈中,也就是这里。而且方法的局部变量以及函数地址的调入和调出,都存放在这里,所以,JAVA的一个对象,有两部分,对象本身的值在堆中,而引用则在栈中。当栈空间不够时,比如递归层次太深,就会导致java.lang.StackOverflowError异常。

局部变量表存放了编译期可知的各种基本数据类型(boolean,byte,char,short,int,float,long,double)、对象引用(reference类型)和returnAddress类型(指向了一条字节码指令的地址)。

在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。


3.本地方法栈Native Method stack:

本地方法栈与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行JAVA方法服务的,而本地方法栈则是为虚拟机使用到的本地方法服务。本地方法栈是为JVM运行Native方法准备的空间,虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。例如Sun HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一。

在JVM规范中没有对这个区域的严格限制,他可以由不同的JVM实现者3实现,但是他和其他存储区一样也会抛出OutOfMemoryError和StackOverflowError。

4.方法区 Method area:

方法区(Method Area)与Java堆一样,是各个线程共享的内存区域它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

方法区域存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息等。当开发人员在程序中通过Class对象中的getName等方法来获取信息时,这些数据都来源于方法区域。

方法区域也是全局共享的,因此会涉及到多线种访问的同步问题,方法区在一定的条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出JAVA.lang.OutOfMemoryError:PermGen full的错误信息。

在Sun JVM中这块区域对应的为Permanet Generation,又称为持久代, Permanet Generation实际上并不等同于方法区,只不过是Hotspot JVM用Permanet Generation来实现方法区而已,有些虚拟机也没有PermSpace而是用其他机制来实现方法区。

运行时常量池(Runtime Constant Pool)是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

既然运行时常量池是方法区的一部分,自然会受到方法区内存的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常。


5.Heap  堆空间:

对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。

Java堆是垃圾收集器管理的主要区域。如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java堆中还可以细分为:新生代和老年代;再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。

堆空间是JAVA对象生死存亡的地区,JAVA对象的出生,成长,死亡都在这个区域完成。JAVA程序在运行时创建的所有类实例或数组都放在堆中。

每一个JAVA程序独占一个JVM实例, 一个JVM实例只存在一个堆空间,因些每个JAVA程序都有它自己的堆空间,它们不会彼此干扰。

同一个JAVA程序的多个线程都共享着同一个堆空间,所以就需要考虑多线程访问对象(堆数据)的同步问题。

Sun的 HotSpot虚拟机对于堆内存共划分为二大部分:
年轻代 / 新生代( Young Generation )、老年代( Old Generation)




大部分新生成的对象都放在Eden中,当Eden内存不够用时,触发Young GC,这时,会将Eden中不能被释放的对象以及S0中幸存的对象,都Copy到S1中,并且将经历过几次Young GC还幸存的新生代对象,放入到Old Generation中,然后释放Eden和S0。

所以S0和S1是来回切换使用的,保存新生代中还不能被释放的对象,所以S0和S1总有一个会是空的,当然在发生Youg GC时,对象正在COPY时会是二者都有数据;如果经历几次Young GC时新生代还是满的,还不能够接收Eden中过来的幸存对象,就会抛出java.lang.OutOfMemorryError:java heap space;

如果在进行Youg GC时,发现S0不够用时,则直接将对象放入Old Generation中,这时如果Old Generation内存也不够时,则触发Full GC,Full GC后如果Old Generation还是满的,就抛出内存溢出异常:java.lang.OutOfMemorryError:java heap space;

所以,假设有一个永不销毁的对象,其经历的过程如下:首先在创建时放入Eden,当某个时刻Eden满了时,通过Young GC放入S0或者S1,其在S0或者S1经历过几次Youg GC后,放入到Old generation中,当Old Generation满了的时候,发生Full GC.


1. Young (年轻代)

jvm规范中的 Heap的一部份, 年轻代又分三个区:一个Eden区,两个Survivor区

(1) 伊甸园(Eden space ):
JAVA堆空间中的大部分对象在此出生,该区的名字因此而得名。也即是说当你的JAVA程序运行时,需要创建新的对象时,JVM都将在该区为你创建一个指定的对象供程序使用。

(2) 幸存者0 区(Survivor 0 space )和幸存者1 区(Survivor1 space ):
当伊甸园的空间用完时,程序又需要创建对象;此时JVM的垃圾回收器将对伊甸园区进行垃圾回收,将伊甸园区中的还存活的对象 移动到幸存者0区或1区。幸存者两个区就是用于存放伊甸园垃圾回收时所幸存下来的JAVA对象。

Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。

2. Tenured (老年代)
在年轻代中经历了多次垃圾回收后仍然存活的对象,就会被放到老年代中。因此,可以认为老年代中存放的都是一些生命周期较长的对象。另外一些大对象也会直接进入老年代,可以通过设置jvm参数来指定多大对象直 接进入老年代( 参数为-XX:PretenureSizeThreshold=1024,单位为字节)。


程序计数器、虚拟机栈、本地方法栈三个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作,这几个区域内不需要过多考虑回收的问题,因为方法结束或线程结束时,内存自然就跟随着回收了。而Java堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期间时才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾回收器所关注的是这部分内存。


JVM内存分配主要基于两种:堆和栈

每个Java应用都唯一对应一个JVM实例,每个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用程序所有的线程共享。在Java中分配堆内存时自动初始化的,所有对象的存储空间都是在堆中分配的,但是这个对象的引用确实在栈中分配的。也就是说在建立一个对象时两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在栈中分配的内存只是一个指向这个堆对象。


-XX:PermSize=10M  -XX:MaxPermSize=10M 限制方法区的大小

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError 限制Java堆的大小,并出现异常时Dump出当前的内存堆转储快照

-Xss128K 限制栈内存容量


运行时栈帧结构:





1.局部变量表:
局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。


2.操作数栈
操作数栈也常被称为操作栈,他是一个后入先出(Last In First Out,LIFO)栈。

3.动态连接
每个栈帧都包含一个执行运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。

4.方法返回地址
当一个方法被执行后,有两种方式退出这个方法。第一种方法是执行引擎遇到任意一个方法返回的字节码指令,这时候可能有返回值传递给上层的方法调用者,是否有返回值和返回值的类型将根据遇到何种方法返回指令决定,这种退出方法的方式成为正常完成出口。

另一种退出方式是,在方法执行过程中遇到了异常,并且这个异常没有在方法体内得到处理,无论是Java虚拟机内部产生的异常,还是代码中使用throw字节码指令产生的异常,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种退出方法的方式成为异常完成出口。一个方法使用异常完成出口的方式退出,是不会给他的上层调用者产生任何返回值的。

无论采用何种退出方式,在方法退出之后,都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复他的上层方法的执行桩体。一般来说,方法正常退出时,调用者的PC计数器的值就可以作为返回地址,栈帧中很可能会保存这个计数器值。而方法异常退出时,返回地址是要通过异常处理器来确定的,栈帧中一般不会保存这行信息。

方法退出的过程实际上等同于把当前栈帧出栈,因此退出时可能执行的操作有:回复上层方法的局部变量表和操作数栈,把返回值(如果有)压入调用者栈帧的操作数中,调整PC计数器的值以指向方法调用指令后面的一条指令等。

5.附加信息


JVM参数的含义:

-Xms :初始堆大小,默认值为物理内存的1/64(<1GB),默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制。

-Xmx :最大堆大小,默认值为物理内存的1/4(<1GB),默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。

-Xmn : 年轻代大小(1.4or lator),此处的大小是(eden + 2 survivor space),整个堆大小=年轻代大小 + 年老代大小 + 持久代大小,增大年轻代后,将会减小年老代大小,此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。

-XX:PermSize :设置持久代(perm gen)初始值,默认值为物理内存的1/64

-XX:MaxPermSize :设置持久代最大值,默认值为物理内存的1/4

-Xss :每个线程的堆栈大小,JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右,一般小的应用, 如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。

-XX:NewRatio :年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代),-XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5,Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置。

-XX:SurvivorRatio :Eden区与Survivor区的大小比值,默认值设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。

-XX:LargePageSizeInBytes :内存页的大小不可设置过大, 会影响Perm的大小,默认值为128m。















  • 大小: 104 KB
  • 大小: 21.8 KB
  • 大小: 88.6 KB
  • 大小: 49.2 KB
  • 大小: 43.7 KB
  • 大小: 24.4 KB
  • 大小: 120.2 KB
  • 大小: 76.4 KB
  • 大小: 120.3 KB
  • 大小: 414.9 KB
分享到:
评论

相关推荐

    java jvm剖析

    java进阶文档,jvm深入研究可以帮助我们更好的理解java虚拟机如何控制内存,可让我们写出性能更好的代码

    深入Java虚拟机_002_深入详解JVM之类加载器深度剖析、根、扩展及系统类加载器

    深入Java虚拟机_002_深入详解JVM之类加载器深度剖析、根、扩展及系统类加载器

    深入JVM剖析Java的线程堆栈

    主要介绍了深入JVM剖析Java的线程堆栈,Java中的堆内存和堆栈原理的应用等知识是深入学习Java的重点,需要的朋友可以参考下

    06尚硅谷_JVM.docx

    ·自Java语言起源始,循序渐进,知识点剖析细致且每章配备大量随堂练习,让你步步为营,学得透彻、练得明白 ·拒绝晦涩难懂的呆板教学,宋老师语言生动幽默,举例形象生动深入浅出,迅速让你把握问题本质,四两拨千...

    深入剖析Java 编程中的中文问题及建议最优解决方法

    本文深入分析了Java 程序设计中Java 编译器对java 源文件和JVM 对class 类文件的编码/解码过程,通过此过程的解析透视出了Java 编程中中文问题产生的根本原因,最后给出了建议的最优化的解决Java 中文问题的方法。

    一次性精通JVM JAVA虚拟机

    第2章 字节码文件,深入剖析字节码文件的全部组成结构,以及javap和jbe可视化反解析工具的使用。 第3章 类的加载、解释、编译,本章节带你深入理解类加载器的分类、范围、双亲委托策略,自己手写类加载器,理解字节...

    xmljava系统源码-Superman:Superman是什么:构建JavaAndroid高级开发技术的知识体系,从基础不断打怪升级成为超人

    xml java系统源码 Superman Superman是什么:构建Java Android 高级开发技术的知识体系,Android ...深入剖析JVM [写作中] JVM底层原理 并发编程成神之路 [写作中] 线程的本质 网络编程和Netty [敬请期待

    程序员圆桌会议资料

    杭州程序员圆桌会资料1,深入剖析JVM,讲的恨透很详细,JVM爱好者的最爱

    Java程序性能优化

    《Java程序性能优化:让你的Java程序更快、更稳定》以Java性能调优为主线,系统地阐述了与Java性能优化相关...专 注于Java应用程序的优化方法、技巧和思想,深入剖析软件设计层面、代码层面、JVM虚拟机层面的优化方法。

    Java-相关课程视频网盘地址.rar

    垂直打击之JVM剖析 大数据-大数据批处理之Hive详解 大数据-海量日志收集利器:Flume 分布式服务Dubbo的前世今生 高效程序员如何优雅落地需求 大数据课程大纲 架构师视角分析架构演进带来的挑战 架构师专场之享受一场...

    传智播客_Java基础_Java内存结构

    李若亮老师带你深入剖析Java编程中所内存涉及的方方面面,从JVM的内存申请,到Java语言的内存加载以及Java语言的内存回收,方方面面面,逐一剖析,体会Java语言的独特魅力。正如范大师所说:你不仅要知道它是怎么来...

    Java性能优化实战视频全集

    03 深入剖析:哪些资源,容易成为瓶颈?.mp4 04工具实践:如何获取代码性能数据?.mp4 05 工具实践;基准测试JMH,精确测量方法性能.mp4 06 案例分析:缓冲区如何让代码加速.mp4 07 案例分析:无处不在的缓存,高...

    Java 性能优化实战 21 讲2021年

    │ 03 深入剖析:哪些资源,容易成为瓶颈?.mp4 │ 04 工具实践:如何获取代码性能数据?.mp4 │ 05 工具实践:基准测试 JMH,精确测量方法性能.mp4 │ 06 案例分析:缓冲区如何让代码加速.mp4 │ 10 案例分析...

    The Java Virtual Machine Specification(Second Edition)

    The JavaTM Virtual Machine Specification, Second Edition(深入剖析JVM的运行机制):Java 经典书 大家反应说下载后无法看。解决办法(windows):右键-&gt;属性-&gt;解除锁定。问题就解决了

    Java虚拟机的深入研究.docx

    本文通过对JVM的体系结构的深入研究以及一个Java程序执行时虚拟机的运行过程的详细分析,意在剖析清楚Java虚拟机的机理。

    圣思园Java视频 java se & java web

    深入详解JVM之类加载器深度剖析, Javascript, Node,

    Spring技术内幕:深入解析Spring架构与设计原理

     国内第一本基于spring3.0的著作,从源代码的角度对spring的内核和各个主要功能模块的架构、设计和实现原理进行了深入剖析。你不仅能从木书中参透spring框架的优秀架构和设计思想,而且还能从spring优雅的实现源码...

    Java 并发编程原理与实战视频

    第15节synchronized保证线程安全的原理(jvm层面)00:25:03分钟 | 第16节单例问题与线程安全性深入解析00:27:15分钟 | 第17节理解自旋锁,死锁与重入锁00:24:58分钟 | 第18节深入理解volatile原理与使用00:28:30...

Global site tag (gtag.js) - Google Analytics