jdk源码解析(初识)

jdk源码解析(初识)

源码解析的过程

是经历 JDK —>JRE—>JVM三部重要的步骤

内部结构图

Java各种集成开发工具:类似我们在用的IDEA,MyEclipse等开发工具。

JDK:是面向开发人员使用的SDK,它提供了Java的开发环境和运行环境,简称软件开发包。

JRE:JRE运行环境是一个软件,它可以使你的计算机系统可以运行Java程序。

JVM:Java虚拟机,可以使Java语言在不同的平台上运行时不需要重新编译。真正实现了跨平台,跨区域运行

以上这些工具都是运行在OS操作系统上的

JVM解析

了解jvm要了解jvm的里面的结构

分开解释

程序计数器

它是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器。

每一条JVM线程都有自己的PC寄存器,各条线程之间互不影响,独立存储,这类内存区域被称为“线程私有”内存

在任意时刻,一条JVM线程只会执行一个方法的代码。该方法称为该线程的当前方法(Current Method)

如果该方法是java方法,那PC寄存器保存JVM正在执行的字节码指令的地址

如果该方法是native,那PC寄存器的值是undefined。

此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。 +

Java虚拟机栈

Java虚拟机栈也是线程私有的,每一个jvm线程都有自己的Java虚拟机栈,这个栈与线程同时创建,它的生命周期和线程相同

虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

JVM stack 可以被实现成固定大小,也可以根据计算动态扩展。

如果采用固定大小的JVM stack设计,那么每一条线程的JVM Stack容量应该在线程创建时独立地选定。JVM实现应该提供调节JVM Stack初始容量的手段;如果采用动态扩展和收缩的JVM Stack方式,应该提供调节最大、最小容量的手段。

如果线程请求的栈深度大于虚拟机所允许的深度将抛出StackOverflowError;

如果JVM Stack可以动态扩展,但是在尝试扩展时无法申请到足够的内存时抛出OutOfMemoryError。

本地方法栈

本地方法栈与虚拟机栈作用相似,后者为虚拟机执行的Java方法服务,而前者为虚拟机用到的Native方法服务。

字面意思就是本地方法栈是针对外来方法操作。

Java堆

虚拟机管理的内存中最大的一块,同时也是被所以的线程所共享的,它在虚拟机启动时创建,它存在的意义就是存放对象实例。

几乎所有的对象实例以及数组都要在这里分配内存。这里面的对象被自动管理,也就是俗称的GC(Garbage Collector)所管理。用就是了,有GC扛着呢,

Java堆只要逻辑上是连续的即可,它使用的内存不需要保证是物理连续的。

Java堆是垃圾回收集器(GC)管理的主要区域,可以细分为"新生代和老年代,永久代"。

如果堆中没有内存完成实例分配并且堆也无法扩展,就会抛OutOfMemoryError。

方法区

跟堆一样是被各个线程共享的内存区域,用于存储以被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。

方法区在虚拟机启动的时候创建

方法区的容量可以固定大小的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩。

方法区在实际内存空间中可以是不连续的。

Java虚拟机实现应当提供给程序员或者最终用户调节方法区初始容量的手段,对于可以动态扩展和收缩方法区来说,则应当提供调节其最大、最小容量的手段。

对于习惯在hotspot虚拟机上开发,很多人愿意将方法区叫“永久代”本质上两者不等价。只是Hotspot的垃圾收集器可以像管理java堆一样管理这部分内存而已。

当方法区无法满足内存分配需求时就会抛OutOfMemoryError。
运行时常量池

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

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

直接内存

直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域

它就相当于一个物理内存,但是这部分内存要是被频繁使用,也是会出现OutOfMemoryError异常出现。

JDK1.4加的NIO中,ByteBuffer有个方法是allocateDirect(int capacity) ,这是一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
显然,本机直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,则肯定还是会受到本机总内存的大小及处理器寻扯空间的限制,服务器管理员配置虚拟机参数时,一般会根据实际内存设置-Xmx等参数信息,但经常会忽视直接内存,使得各个内存区域的总和大于物理内存限制(包括物理上的和操作系统级的限制),从而导致动态扩展时出现OutOfMemoryError异常。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值