A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 裤头多佛祖 中级黑马   /  2016-7-8 10:55  /  964 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

{:3_67:}自古一楼不说事

7 个回复

倒序浏览
回复 使用道具 举报
   2楼传的图,不知道怎么就成了那个样子,有兴趣看图的可以找度娘.结构图包含了类加载器(ClassLoader)主要用来用来加载 class字节码到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源文件在经过 Javac之后就被转换成 Java 字节码文件(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每一个这样的实例用来表示一个 Java 类。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载。
回复 使用道具 举报
本宝宝先去吃饭了,今天休息,早上还没吃饭里
回复 使用道具 举报
楼主,你要继续努力啊!你是bbs的希望啊!你是网络文学的希望啊!你是整个文学界的希望啊!你是整个人类的希望啊!你是整个太阳系的希望啊!你是整个异次元空间的希望啊!
回复 使用道具 举报
系统提供的类装载器主要由下面三个:
启动类加载器(bootstrap classloader):它用来加载 Java 的核心库,是用原生代码(本地代码,与平台有关)来实现的,并不继承自java.lang.ClassLoader。这个类加载器负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识加的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用。
扩展类加载器(extensions classloader):扩展类加载器是由 Sun 的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader) 实现的。它负责将 < Java_Runtime_Home >/lib/ext 或者由系统变量java.ext.dir 指定位置中的类库加载到内存中
应用程序类加载器(application classloader):系统类加载器是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的,由于这个类加载器是ClassLoader中getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序默认的类加载器。
用户自定义的类装载器
用户自定义的类装载器是普通的Java对象,它的类必须派生自java.lang.ClassLoader类。ClassLoader中定义的方法为程序为程序提供了访问类装载器机制的接口。此外,对于每一个被装载的类型,Java虚拟机都会为它创建一个java.lang.Class类的实例来代表该类型。和所有其它对象一样,用户自定义的类装载器以有Class类的实例都放在内存中的堆区,而装载的类型信息则都放在方法区。
Java运行数据区域也就是Java内存区,常常出现内存异常的地方(OOM等),也是我们最关心的一个地方。
大家说到内存往往会想到“栈”和“堆”,但Java虚拟机内存并不是仅仅只有这两个区域。 下面依次介绍java虚拟机内存的各个区域,介绍这些区域的作用、服务对象以及其中可能产生的问题。
回复 使用道具 举报
程序计数器Program Counter Register(PRC)
如果大家了解过相对底层一点的东西如汇编,嵌入式等相关学习,对程序计数器PRC应该不会陌生,当然在Java里面程序计数器也有它的作用。
一、在Java内存里面程序计数器只占一块很小的区域。
二、它的作用可以看作是当前线程所执行的字节码的行号指示器,通过改变PRC的值进行字节码寻指。分支、循环、跳转、异常处理等都是依赖它完成。
三、每一条线程都拥有一个自己私有的PRC,且每个CRC互不干扰。同时我们可以将CRC称为“线程私有”的内存。
四、如果虚拟机正在执行Java方法,PRC记录的是正在执行的虚拟机字节码指令的地址。如果执行的是native方法,那么PRC为空。
五、PRC是唯一一个在内存区域不会出现OutOfMemoryError的地方
Java虚拟机栈(Java Virtual Machine Stacks )
虚拟栈主要描述的是Java方法执行的内存模型(你需要明白:每一个Java线程会有(私有)一个相对应的虚拟机栈区,栈的一段区域叫做栈帧):每个方法被执行一次,都会在栈区内创建一个栈帧(Stack Frame),用于存储局部变量表,操作栈、动态链接、方法出口等信息。每一个方法的执行到完成过程代表着一个栈帧的入栈和出栈过程。
局部变量表存放着编译期可知的基本数据类型(boolean,byte、char、short、int、float、long、double)、对象引用和returnAddress(指向一条字节码指令地址)。其中long和double占两个局部变量空间(Slot),其余数据类型只占一个。局部变量表的内存空间大小在编译期间就已经分配,在方法执行的过程中不会发生变化。
在Java虚拟机规范中,在这个区域规定了两种内存异常:
StackOverflowError:栈的请求深度大于虚拟机的允许最大深度。
OutOfMemoryError:(大部分Java虚拟机都允许在内存不够的情况下,动态扩展内存,同时也允许固定内存长度的虚拟机栈),当扩展时无法申请到足够的内存就会抛出此异常
回复 使用道具 举报
直接内存(Direct Memory)
不属于运行时是数据区的一部分,也不是虚拟机规范的内存区域,但这一部分也常常被使用,而且抛出OOM。
在JDK1.4中新加入了NIO(new input/output),引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用本地方法库直接分配内存,然后通过一个存储在java heap 里的DirectByteBuffer对象作为这快内存的引用进行操作。
上面已经将Java虚拟机运行时数据区的各区域的作用,存储内容,以及抛出的异常等做出了介绍(更具体的介绍,大家可以自己搜索下)。其中程序计数器,虚拟机栈,本地方法栈随线程生,随线程亡;栈中的栈帧随着方法的执行和退出而有条不絮的进行着出栈和进栈。每一个栈帧中分配多少内存,基本上在类的结构确定下来就已知了,因此这几个区域内存的分配和回收都具有确定性,因为在方法结束或者线程结束,内存自然而然的跟着回收了。
      Java堆和方法区则不一样,一个接口中的多个类的实现,一个方法多个分支,多可能造成内存不一样,不确定性,只有当程序处于运行时我们才知道,有多少个对象被创建,这部分的内存分配和回收都是动态的。因此接下来主要介绍这一部分的垃圾回收与内存分配
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马