1、栈
栈(Stack):存放的都是方法的 局部变量。方法的运行一定要在栈中运行。
- 局部变量:方法的参数,或是方法 大括号{ } 内部的变量
- 作用域:一旦超出 作用域,立刻从 栈内存 当中弹出
2、堆
堆(Heap):凡是 new 出来的东西,都在堆当中。(如果是在方法内定义的引用- 类型的局部变量,该引用类型的对象 是在堆中,该对象的变量名 是 在栈中,且变量名存储的是 对象地址 -- 该对象在堆中的地址)
堆内存里面的东西都有一个地址值:16进制
堆内存里的数据,都有默认值。规则:
整数 -- 默认为 0
浮点数 -- 默认为 0.0
字符 -- 默认为 ‘\u0000’
布尔 -- 默认为 false
引用类型 -- 默认为 null
3、方法区
方法区:存储 .class 相关信息,包括方法的信息(即,方法的定义等)
4、本地方法栈
与操作系统相关
5、寄存器
与 CPU 相关
引起内存溢出的原因有很多种,常见的有以下几种:
- 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
- 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
- 代码中存在死循环或循环产生过多重复的对象实体;
- 使用的第三方软件中的BUG;
- 启动参数内存值设定的过小;
内存溢出的解决
1.第一步,就是修改JVM启动参数,直接增加内存。
2.第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。
3.第三步,安排有经验的编程人员对代码进行走查和分析,找出可能发生内存溢出的位置。重点排查以下几点:
l 检查代码中是否有死循环或递归调用。
l 检查是否有大循环重复产生新对象实体。
l 检查对数据库查询中,是否有一次获得全部数据的查询。
l 检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。
4.第四步,使用内存查看工具动态查看内存使用情况。
一、JDK
JDK(Java SE Development Kit),Java标准开发包,它提供了编译、运行Java程序所需的各种工具和资源,包括Java编译器、Java运行时环境,以及常用的Java类库等。
下图是JDK的安装目录:
二、JRE
JRE( Java Runtime Environment) 、Java运行环境,用于解释执行Java的字节码文件。普通用户而只需要安装 JRE(Java Runtime Environment)来运行 Java 程序。而程序开发者必须安装JDK来编译、调试程序。
下图是JRE的安装目录:里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib和起来就称为jre。
三、JVM
JVM(Java Virtual Mechinal),Java虚拟机,是JRE的一部分。它是整个java实现跨平台的最核心的部分,负责解释执行字节码文件,是可运行java字节码文件的虚拟计算机。所有平台的上的JVM向编译器提供相同的接口,而编译器只需要面向虚拟机,生成虚拟机能识别的代码,然后由虚拟机来解释执行。
当使用Java编译器编译Java程序时,生成的是与平台无关的字节码,这些字节码只面向JVM。不同平台的JVM都是不同的,但它们都提供了相同的接口。JVM是Java程序跨平台的关键部分,只要为不同平台实现了相应的虚拟机,编译后的Java字节码就可以在该平台上运行。
四、区别与联系
- JDK 用于开发,JRE 用于运行java程序 ;如果只是运行Java程序,可以只安装JRE,无序安装JDK。
- JDk包含JRE,JDK 和 JRE 中都包含 JVM。
- JVM 是 java 编程语言的核心并且具有平台独立性。