java内存区域与内存异常

程序运行对于各部分:
程序运行的过程
java虚拟机运行时的数据区
在这里插入图片描述
线程隔离的数据区:虚拟机栈,本地方法栈,程序计数器。三者是线程私有的。
java堆和方法区,所有线程共享的内存区域。

程序计数器:当前线程所执行的字节码的行号指示器。
虚拟机栈:java方法执行的内存模型。每个方法在执行的同时都会创建一个栈帧。–使用到的java方法服务。
栈帧存储局部变量表(存放编译器可知的各种基本数据类型,对象引用等),操作数栈,动态链接,方法出口等信息,每一个方法从调用到执行完成,就对应着一个栈帧在虚拟机栈中的入栈到出栈的过程。
虚拟机栈这个区域,规定两种异常。StackOverflowError–线程请求的栈深度大于虚拟机允许的深度,OutofMerrory–虚拟机栈可以动态扩展,扩展时无法申请到足够内存
本地方法栈:虚拟机中使用到的native方法服务。 StackOverflowError, OutofMerrory。


Java的内存区中,为线程共有的有三部分:Java堆,方法区,直接内存。其中方法区中包含运行时常量池。直接内存并不属于Java的常规内存区。
java堆:存放对象实例。若在堆中没有内存为实例分配,则堆将无法再扩展—OutofMerrory
方法区(Non-Heap) :用于存储已被虚拟机加载的类信息,常量,静态变量和即时编译器编译后的代码等数据。

  1. Java堆是被所有线程共享的一块内存,在启动虚拟机时创建。通常,所有的对象实例及数组都要在堆上分配。但并不绝对。
  2. Java堆可扩展。其内存在物理上可以不连续。当Java堆无法再扩展时,将抛出内存不足异常。
  3. Java的垃圾收集器主要用于管理Java堆。
  4. 方法区用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等。同样是被各个线程共享。方法区可扩展,不需要内存在物理上连续,并可选择不进行垃圾收集。因为这部分的垃圾主要是针对常量池的回收和对类型的卸载,所以相对清理较少。
  5. 直接内存是一片独立的内存区,主要用于IO操作。直接内存不受Java堆大小的限制。 但是动态扩展,会出现 --OutofMerrory

区分两个概念: JAVA方法和本地方法 运行时常量池和Class文件常量池见如下

A、
运行时常量池和Class文件常量池 https://www.jianshu.com/p/c7f47de2ee80
B、
JAVA中有两种方法:JAVA方法和本地方法
JAVA方法是由JAVA编写的,编译成字节码,存储在class文件中
本地方法是由其它语言编写的,编译成和处理器相关的机器代码
本地方法保存在动态链接库中,即.dll(windows系统)文件中,格式是各个平台专有的
java方法与平台无关。
1、什么是native方法?为什么用本地方法?JVM怎样使Native Method跑起来?
(1)一个Native Method就是一个java调用非java代码的接口,其方法的实现是用非java语言实现的。
native暗示这些方法是有实现体的,只不过这些实现体是非java的,但是abstract却显然的指明这些方法无实现体。native
与其它java标识符连用时,其意义同非Native Method并无差别。如果一个含有本地方法的类被继承,子类会继承这个本地方法并且可以用java语言重写这个方法。
(2) java使用起来非常方便,然而有些层次的任务用java实现起来不容易,或者我们对程序的效率很在意时,问题就来了。
java应用需要与java外面的环境交互。这是本地方法存在的主要原因,你可以想想java需要与一些底层系统如操作系统或某些硬件交换信息时的情况。本地方法正是这样一种交流机制:它为我们提供了一个非常简洁的接口,而且我们无需去了解java应用之外的繁琐的细节。
通过使用本地方法,我们得以用java实现了jre的与底层系统的交互,甚至JVM的一些部分就是用C写的,还有,如果我们要使用一些java语言本身没有提供封装的操作系统的特性时,我们也需要使用本地方法。
例如: Sun的解释器是用C实现的,这使得它能像一些普通的C一样与外部交互。jre大部分是用java实现的,它也通过一些本地方法与外界交互。例如:类java.lang.Thread 的 setPriority()方法是用java实现的,但是它实现调用的是该类里的本地方法setPriority0()。这个本地方法是用C实现的,并被植入JVM内部,

(3) 当一个类第一次被使用到时,这个类的字节码会被加载到内存,并且只会加载一次。在这个被加载的字节码的入口维持着一个该类所有方法描述符的列表,这些方法描述符包含这样一些信息:方法代码存于何处,它有哪些参数,方法的描述符(public之类)等等。
如果一个方法描述符内有native,这个描述符块将有一个指向该方法的实现的指针。这些实现在一些DLL文件内,但是它们会被操作系统加载到java程序的地址空间。当一个带有本地方法的类被加载时,其相关的DLL并未被加载,因此指向方法实现的指针并不会被设置。这些DLL的加载是通过调用System.loadLibrary(String filename)或System.load(String filename)方法实现的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值