java基础知识总结
2021-04-16 14:59:39 2 举报
AI智能生成
java基础知识总结(不断完善中)
作者其他创作
大纲/内容
基础语法
数据类型
基本类型
整数
byte
8位1个字节
short
16位2个字节
int
32位4个字节
long
64位8个字节
boolean
char
16位2个字节
小数
double
64位8个字节
float
32位4个字节
枚举类型
引用类型
数据类型转换
隐式转换
系统默认将其转换为我们需要的数据类型
强制转换
基本数据类型之间转换规则
标识符命名规则
可以由数字、字母、下划线、$符号组成,但是不能是关键词,不能以数字开头
运算符
+
-
*
/
%
位运算符
++ & --
逻辑运算符(也叫作短路运算符)
||
或,两边条件有一个满足true,则结果为true
&&
与, &&两边条件必须返回boolean类型,两边同时为true则结果为true
流程控制
循环结构
分类
do ..while循环
while循环
for循环
for each
相关关键字
continue
continue 只能用于循环体中,表示退出当前循环,继续下一次循环
break
break 表示退出整个循环或者判断
分支结构
if
if..else
switch case
顺序结构
关键字
goto是java的保留关键字
数组
基本使用
定义
初始化
new
静态初始化
基本属性
length
下标运算取值
Arrays工具类
排序
复制
...更多查看Api
二维数组
定义
Api
集合框架
基本介绍
对线性表,链表,哈希表这些常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构。因此,我们一般的程序员不必自己开发相关的方法。集合(框架):java提供了一组对数组、链表数据结构操作的API,这组API即集合;存在于java.util
分类
collection(接口)
list(接口)
ArrayList
List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。 (来自jdk1.6)
LinkedList
List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。 (来自jdk1.6)
Vector
Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。 (来自jdk1.6)
set(接口)
HashSet(最常用的set实现类)
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。(来自jdk1.6)
TreeSet
基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。(来自jdk1.6)
map(接口)
HashMap
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。(来自jdk1.6)
HashTable
此类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null 对象都可以用作键或值。 (来自jdk1.6)
lang包
GC
什么是GC?
GC是垃圾收集的意思(Gabage Collection)
GC的场所?
堆
总的来看,GC在堆中,分为两个部分,一部分是年轻代(GC频率高,速度快),另一部分是老年代(GC频率较低),Java虚拟机在进行垃圾回收时,将Eden和Survivor中还存活着的对象进行一次性地复制到另一块Survivor空间上,直到其两个区域中对象被回收完成,当Survivor空间不够用时,需要依赖其他老年代的内存进行分配担保。在老生代中不仅存放着这一种类型的对象,还存放着大对象(需要很多连续的内存的对象),当Java程序运行时,如果遇到大对象将会被直接存放到老生代中,长期存活的对象也会直接进入老年代。如果老生代的空间也被占满,当来自新生代的对象再次请求进入老生代时就会报OutOfMemory异常。
进入老年区的判定条件是:每经过一次minor gc,还在年轻代的对象的版本号(“年龄”)会加1,当这个对象到达一定的年纪以后,就会进入老年代。
进入老年区的判定条件是:每经过一次minor gc,还在年轻代的对象的版本号(“年龄”)会加1,当这个对象到达一定的年纪以后,就会进入老年代。
方法区(1.8之前)
就GC回收机制而言,JVM内存模型中的方法区更被人们倾向的称为永久代(Perm Generation),保存在永久代中的对象一般不会被回收。其永久代进行垃圾回收的频率就较低,速度也较慢。永久代的垃圾收集主要回收废弃常量和无用类。以String常量abc为例,当我们声明了此常量,那么它就会被放到运行时常量池中,如果在常量池中没有任何对象对abc进行引用,那么abc这个常量就算是废弃常量而被回收;判断一个类是否“无用”,则需同时满足三个条件
这里回收不是必然的
这里回收不是必然的
该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例
加载该类的ClassLoader已经被回收
该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
GC实现机制
引用计数算法
给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的,这就是引用计数算法的核心。客观来讲,引用计数算法实现简单,判定效率也很高,在大部分情况下都是一个不错的算法。但是Java虚拟机并没有采用这个算法来判断何种对象为死亡对象,因为它很难解决对象之间相互循环引用的问题。
可达性分析算法
这是Java虚拟机采用的判定对象是否存活的算法。通过一系列的称为“GC Roots"的对象作为起始点,从这些结点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
如何主动通知虚拟机进行垃圾回收?
程序员可以手动执行System.gc()或者Runtime.getRuntime().gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。 我们只是“提醒”一下
有关GC的结论(Java编程思想中的片段)
1、垃圾收集并不等于“破坏”!
2、我们的对象可能不会当作垃圾被收掉!
3、垃圾收集只跟内存有关!
概述
Java起源
Java三个平台
Java语言的特性
面向对象
可移植性(一处编译,多处执行)
跨平台
安全性(1、摒弃指针 2、GC垃圾回收机制:自动释放回收长时间不使用对象的内存)
并发性:支持多线程
JDK & JRE & JVM
开发工具
Java程序的执行过程
其他
面向对象
理解面向对象
首先,面向对象是一种思想,它呢是基于面向过程而言的,这种思想是对数据的一种优化
其次,理解对象概念,什么是对象?对象就是类的一个实例,什么是类?类就是对一类事物的抽象,这类事物的共同特性就是程序中的属性,共同的行为就是方法。
例如:动物这个类。有属性name,有方法eat()。动物类的对象:狗,狗呢就具有name的属性和吃的行为。
其次,理解对象概念,什么是对象?对象就是类的一个实例,什么是类?类就是对一类事物的抽象,这类事物的共同特性就是程序中的属性,共同的行为就是方法。
例如:动物这个类。有属性name,有方法eat()。动物类的对象:狗,狗呢就具有name的属性和吃的行为。
三大特性
封装
隐藏了对象的具体细节。提高了复用性和安全性
继承
两个类之间有一些的属性和方法的重复。就使用继承,这样既简化了代码,也提高了代码的复用性
子类可以继承到父类,public protect 的方法和属性
java中是“单继承”
object是所有类的父类
多态
继承是多态的前提。体现在:父类对象的引用可以指向子类对象,这样提高了程序的扩展性
三个过程
OOA 面向对象分析
OOP 面向对象编程
OOD 面向对象设计
类相关
基本概念
类是什么?
是一类事物的描述,程序中为class
两个基本的特点
属性
即一类事物具有的共有特点或者特性;程序中为全局变量(成员变量)
方法
一类事物具有的动作,或者行为
定义
使用关键字new就可以创建类对象,使用对象.方法,对象.属性就可完成调用
创建一个对象都在内存中做了什么事情?
分类
抽象类
定义
抽象类是使用abstract关键字来修饰的类
特点
细节
接口
定义
接口是使用interface来修饰的类
特点
好处
一般类
直接使用class声明的类
内部类
在一个类的内部,声明一个类,这个类称为内部类
抽象类和接口的区别?
其他
方法重载
overload 发生在 当前类中 方法名相同,参数个数或者参数类型不同;
方法重写
override 发生在 子类中,子类的方法与父类方法名、参数个数、参数类型,返回值类型完全相同,并且访问权限不能严于父类
构造方法
基本说明
该方法与类名相同;没有返回值也不可以使用void 声明,默认public修饰
任何一个类,都有一个无参数的构造方法; 对象实例化时被执行
与普通方法的区别
构造方法是在对象创建时,就被调用,构造方法常用于初始化成员变量,而且初始化动作只执行一次。
一般方法,是对象创建后,需要调用才执行,可以被调用多次。
继承
子类继承父类,可以继承父类中 非私有的方法和属性
其他
关键字:extends
实现
关键字:implements
一个类实现一个接口时候使用该关键字
注意,接口是特殊的抽象类,实现以后要重写所有的抽象方法
设计原则
单一职责原则
单一职责原则(SRP:Single responsibility principle)又称单一功能原则,
面向对象五个基本原则(SOLID)之一。它规定一个类应该只有一个发生变化的原因。
面向对象五个基本原则(SOLID)之一。它规定一个类应该只有一个发生变化的原因。
开闭原则
在面向对象编程领域中,开闭原则规定
“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”,
这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。
“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”,
这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。
依赖倒置原则
依赖倒置原则(Dependence Inversion Principle)是程序要依赖于抽象接口,不要依赖于具体实现。
简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
里氏替换原则
里氏替换原则,OCP作为OO的高层原则,主张使用“抽象(Abstraction)”和“多态(Polymorphism)”将设计中的静态结构改为动态结构,维持设计的封闭性。“抽象”是语言提供的功能。“多态”由继承语义实现。
接口隔离原则
客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。
迪米特法则
迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),
一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,
只和朋友通信,不和陌生人说话。英文简写为: LoD.
一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,
只和朋友通信,不和陌生人说话。英文简写为: LoD.
自动拆装箱
Java有8种基本类型,每种基本类型又有对应的包装类型。在Java中,一切都以对象作为基础,但是基本类型并不是对象,如果想以对象的方式使用这8中基本类型,可以将它们转换为对应的包装类型。基本类型和包装类型的对应
异常 & 错误
异常
异常即exception
可以预知、可以通过修改程序来弥补"错误",可避免的
可以预知、可以通过修改程序来弥补"错误",可避免的
错误
错误即error
无法预知的,系统级别的,程序员修改程序是无法修复的;例如:系统宕机,JVM挂掉了
无法预知的,系统级别的,程序员修改程序是无法修复的;例如:系统宕机,JVM挂掉了
泛型
泛指一种类型
IO流
概念
流是一组有序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
分类
按照数据流向分
输入流
相对于内存,向内存中写入
输出流
相对于内存,从内存往外读
按照流的数据传输的格式
字节流
以字节为单位读取;一般用于读写文件,读写诸如图象或声音等的二进制数据。
字符流
以字符为单位读取;一般用于读写文件中文本内容
xml
XML是一种可拓展文本标记语言
jdbc
常用数据库驱动程序和url格式
Oracle数据库:
驱动程序包名:ojdbc5.jar
驱动程序包名有可能会变
驱动类的名字:oracle.jdbc.driver.OracleDriver
JDBC URL:jdbc:oracle:thin:@dbip:port:databasename
JDBC URL中黑色字体部分必须原封不动的保留,为该驱动识别的URL格式。红色字体部分需要根据数据库的安装情况填写。其中各个部分含义如下:
dbip 为数据库服务器的IP地址,如果是本地可写:localhost或127.0.0.1
port 为数据库的监听端口,需要看安装时的配置,缺省为1521
databasename 为数据库的SID,通常为全局数据库的名字
例如:jdbc:oracle:thin:@localhost:1521:XE
Mysql数据库
驱动程序包名:mysql-connector-java-5.1.26-bin.jar
说明:驱动程序包名有可能会变
驱动类的名字:com.mysql.jdbc.Driver
JDBC URL:jdbc:mysql://dbip:port/databasename
JDBC URL中黑色字体部分必须原封不动的保留,为该驱动识别的URL格式。红色字体部需要根据数据库的安装情况填写。其中各个部分含义如下:
dbip –为数据库服务器的IP地址,如果是本地可写:localhost或127.0.0.1
port –为数据库的监听端口,需要看安装时的配置,缺省为3306
databasename –数据库的名字。
例如:jdbc:mysql://localhost:3306/XE
Oracle数据库:
驱动程序包名:ojdbc5.jar
驱动程序包名有可能会变
驱动类的名字:oracle.jdbc.driver.OracleDriver
JDBC URL:jdbc:oracle:thin:@dbip:port:databasename
JDBC URL中黑色字体部分必须原封不动的保留,为该驱动识别的URL格式。红色字体部分需要根据数据库的安装情况填写。其中各个部分含义如下:
dbip 为数据库服务器的IP地址,如果是本地可写:localhost或127.0.0.1
port 为数据库的监听端口,需要看安装时的配置,缺省为1521
databasename 为数据库的SID,通常为全局数据库的名字
例如:jdbc:oracle:thin:@localhost:1521:XE
Mysql数据库
驱动程序包名:mysql-connector-java-5.1.26-bin.jar
说明:驱动程序包名有可能会变
驱动类的名字:com.mysql.jdbc.Driver
JDBC URL:jdbc:mysql://dbip:port/databasename
JDBC URL中黑色字体部分必须原封不动的保留,为该驱动识别的URL格式。红色字体部需要根据数据库的安装情况填写。其中各个部分含义如下:
dbip –为数据库服务器的IP地址,如果是本地可写:localhost或127.0.0.1
port –为数据库的监听端口,需要看安装时的配置,缺省为3306
databasename –数据库的名字。
例如:jdbc:mysql://localhost:3306/XE
学习网站
jvm
概述
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
组成
jdk 1.8之后
元数据区取代了1.8版本以前的永久代。元数据区和永久代本质上都是方法区的实现。
存储已被虚拟机加载的类信息。随着JDK8的到来,JVM不再有方法区(PermGen),原方法区存储的信息被分成两部分:1、虚拟机加载的类信息,2、运行时常量池。分别被移动到了元空间和堆中。
存储已被虚拟机加载的类信息。随着JDK8的到来,JVM不再有方法区(PermGen),原方法区存储的信息被分成两部分:1、虚拟机加载的类信息,2、运行时常量池。分别被移动到了元空间和堆中。
jdk 1.8之前
VM Stack(虚拟机栈,也有翻译成JAVA 方法栈的)
线程私有区域,之所以被称为“java方法栈”是因为,虚拟机栈是为java方法(也就是字节码)服务的,每个方法被执行的时候,都会同步创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每个方法被调用直到执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
这个内存区域规定了两类异常情况,1、如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常;2、如果java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存时,会抛出OutOfMemoryError异常。
这个内存区域规定了两类异常情况,1、如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常;2、如果java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存时,会抛出OutOfMemoryError异常。
栈帧
概念
Java虚拟机以方法作为最基本的执行单元,“栈帧”(Stack Frame)则是用于支持虚拟机进行方法
调用和方法执行背后的数据结构,它也是虚拟机运行时数据区中的虚拟机栈(Virtual Machine
Stack)的栈元素。
调用和方法执行背后的数据结构,它也是虚拟机运行时数据区中的虚拟机栈(Virtual Machine
Stack)的栈元素。
结构组成
局部变量表
局部变量表(Local Variables Table)是一组变量值的存储空间,用于存放方法参数和方法内部定义
的局部变量。在Java程序被编译为Class文件时,就在方法的Code属性的max_locals数据项中确定了该方
法所需分配的局部变量表的最大容量。
的局部变量。在Java程序被编译为Class文件时,就在方法的Code属性的max_locals数据项中确定了该方
法所需分配的局部变量表的最大容量。
操作数栈
操作数栈(Operand Stack)也常被称为操作栈,它是一个后入先出(Last In First Out,LIFO)
栈。同局部变量表一样,操作数栈的最大深度也在编译的时候被写入到Code属性的max_stacks数据项
之中。操作数栈的每一个元素都可以是包括long和double在内的任意Java数据类型。32位数据类型所占
的栈容量为1,64位数据类型所占的栈容量为2。Javac编译器的数据流分析工作保证了在方法执行的任
何时候,操作数栈的深度都不会超过在max_stacks数据项中设定的最大值。
栈。同局部变量表一样,操作数栈的最大深度也在编译的时候被写入到Code属性的max_stacks数据项
之中。操作数栈的每一个元素都可以是包括long和double在内的任意Java数据类型。32位数据类型所占
的栈容量为1,64位数据类型所占的栈容量为2。Javac编译器的数据流分析工作保证了在方法执行的任
何时候,操作数栈的深度都不会超过在max_stacks数据项中设定的最大值。
动态链接
每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接(Dynamic Linking)。
我们知道Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数。这些符号引用一部分会在类加载阶段或者第一次使用的时候就被转化为直接引用,这种转化被称为静态解析。另外一部分将在每一次运行期间都转化为直接引用,这部分就称为动态连接。
我们知道Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数。这些符号引用一部分会在类加载阶段或者第一次使用的时候就被转化为直接引用,这种转化被称为静态解析。另外一部分将在每一次运行期间都转化为直接引用,这部分就称为动态连接。
方法返回地址
当一个方法开始执行后,只有两种方式退出这个方法。第一种方式是执行引擎遇到任意一个方法
返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者(调用当前方法的方法称为调用
者或者主调方法),方法是否有返回值以及返回值的类型将根据遇到何种方法返回指令来决定,这种
退出方法的方式称为“正常调用完成”(Normal Method Invocation Completion)。
另外一种退出方式是在方法执行的过程中遇到了异常,并且这个异常没有在方法体内得到妥善处
理。无论是Java虚拟机内部产生的异常,还是代码中使用athrow字节码指令产生的异常,只要在本方
法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种退出方法的方式称为“异常调用
完成(Abrupt Method Invocation Completion)”。一个方法使用异常完成出口的方式退出,是不会给它
的上层调用者提供任何返回值的。
返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者(调用当前方法的方法称为调用
者或者主调方法),方法是否有返回值以及返回值的类型将根据遇到何种方法返回指令来决定,这种
退出方法的方式称为“正常调用完成”(Normal Method Invocation Completion)。
另外一种退出方式是在方法执行的过程中遇到了异常,并且这个异常没有在方法体内得到妥善处
理。无论是Java虚拟机内部产生的异常,还是代码中使用athrow字节码指令产生的异常,只要在本方
法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种退出方法的方式称为“异常调用
完成(Abrupt Method Invocation Completion)”。一个方法使用异常完成出口的方式退出,是不会给它
的上层调用者提供任何返回值的。
方法退出的过程实际上等同于把当前栈帧出栈,因此退出时可能执行的操作有:恢复上层方法的
局部变量表和操作数栈,把返回值(如果有的话)压入调用者栈帧的操作数栈中,调整PC计数器的值
以指向方法调用指令后面的一条指令等。
局部变量表和操作数栈,把返回值(如果有的话)压入调用者栈帧的操作数栈中,调整PC计数器的值
以指向方法调用指令后面的一条指令等。
附加信息
《Java虚拟机规范》允许虚拟机实现增加一些规范里没有描述的信息到栈帧之中,例如与调试、
性能收集相关的信息,这部分信息完全取决于具体的虚拟机实现
性能收集相关的信息,这部分信息完全取决于具体的虚拟机实现
其他
每一个栈帧都包括了局部变量表、操作数栈、动态连接、方法返回地址和一些额外的附加信息。
在编译Java程序源码的时候,栈帧中需要多大的局部变量表,需要多深的操作数栈就已经被分析计算
出来,并且写入到方法表的Code属性之中 。换言之,一个栈帧需要分配多少内存,并不会受到程序
运行期变量数据的影响,而仅仅取决于程序源码和具体的虚拟机实现的栈内存布局形式。
在编译Java程序源码的时候,栈帧中需要多大的局部变量表,需要多深的操作数栈就已经被分析计算
出来,并且写入到方法表的Code属性之中 。换言之,一个栈帧需要分配多少内存,并不会受到程序
运行期变量数据的影响,而仅仅取决于程序源码和具体的虚拟机实现的栈内存布局形式。
一个线程中的方法调用链可能会很长,以Java程序的角度来看,同一时刻、同一条线程里面,在
调用堆栈的所有方法都同时处于执行状态。而对于执行引擎来讲,在活动线程中,只有位于栈顶的方
法才是在运行的,只有位于栈顶的栈帧才是生效的,其被称为“当前栈帧”(Current Stack Frame),与
这个栈帧所关联的方法被称为“当前方法”(Current Method)。执行引擎所运行的所有字节码指令都只
针对当前栈帧进行操作
调用堆栈的所有方法都同时处于执行状态。而对于执行引擎来讲,在活动线程中,只有位于栈顶的方
法才是在运行的,只有位于栈顶的栈帧才是生效的,其被称为“当前栈帧”(Current Stack Frame),与
这个栈帧所关联的方法被称为“当前方法”(Current Method)。执行引擎所运行的所有字节码指令都只
针对当前栈帧进行操作
局部变量表
局部变量表存放了编译时期可知的各种java虚拟机基本数据类型(8大基本数据类型)、对象引用(reference类型,它并不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)
这些数据类型在局部变量表中的存储空间以局部变量槽(slot)表示,64位长度的(long和double)会占用两个变量槽,其余数据类型占用一个局部变了表所需要的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小,这里的大小是指,变量槽的数量,虚拟机真正使用多大的内存空间来实现一个变量槽,是由虚拟机决定的。
这些数据类型在局部变量表中的存储空间以局部变量槽(slot)表示,64位长度的(long和double)会占用两个变量槽,其余数据类型占用一个局部变了表所需要的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小,这里的大小是指,变量槽的数量,虚拟机真正使用多大的内存空间来实现一个变量槽,是由虚拟机决定的。
Native Method Stack ( 本地方法栈 )
线程私有区域,本地方法栈为虚拟机执行native方法服务, 这是本地方法栈和虚拟机栈的区别。
与虚拟机栈一样,本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出Stack OverflowError异常和OutOfMemoryError异常
与虚拟机栈一样,本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出Stack OverflowError异常和OutOfMemoryError异常
Method Area(Non-Heap)(方法区)
线程共享区域,通常用来保存装载类的元结构信息。
Heap(堆)
线程共享区域,堆(heap)它是Java虚拟机用来存储对象实例的,比我们在开发过程使用的new对象,只要通过new创建的对象(即所有的对象实例)的内存的对象都在堆分配,(注意,随着逃逸分析技术日渐强大,栈上分配,标量替换等优化手段,已经导致这个特性发生了些变化,所以说 java对象都是分配在堆上也渐渐变得不是那么绝对了)注意一点的是堆中的对象内存需要等待垃圾器(GC)进行回收,也是Java虚拟机共享区。
随着时间的发展,堆里面的经典分区(一个新生代,两个survivor区,一个老年区)也发生了变化,在虚拟机HotSpot里面也出现了不采用分代设计的新垃圾收集器。
随着时间的发展,堆里面的经典分区(一个新生代,两个survivor区,一个老年区)也发生了变化,在虚拟机HotSpot里面也出现了不采用分代设计的新垃圾收集器。
Program Counter Register(程序计数器)
线程私有区域,程序计数器是一块较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
此内存区域是唯一一个在《java虚拟机规范》中没有规定任何oom错误的情况的区域
此内存区域是唯一一个在《java虚拟机规范》中没有规定任何oom错误的情况的区域
jvm内存溢出
溢出情况分析
概述
从图中可以看出,jvm中,堆和方法区会抛出oom异常,虚拟机栈和本地方法栈在多线程环境下可能会发生oom异常,在单线程可能会发生stackOutflowError异常
溢出情况重现
优化配置
java启动参数介绍
标准参数(-)
所有的JVM实现都必须实现这些参数的功能,而且向后兼容
常见参数:
-verbose:class
输出jvm载入类的相关信息,当jvm报告说找不到类或者类冲突时可此进行诊断。
-verbose:gc
输出每次GC的相关情况。
-verbose:jni
输出native方法调用的相关情况,一般用于诊断jni调用错误信息。
非标准参数(-X)
默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容
常见参数:
-Xms
-Xms512m 设置JVM促使内存为512m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmx
-Xmx512m 设置JVM最大可用内存为512M。
-Xmn
-Xmn200m 设置年轻代大小为200M。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss
-Xss128k 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内 存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
非Stable参数(-XX)
此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用
常见参数:
-XX:NewSize和-XX:MaxNewSize
用于设置年轻代的大小,建议设为整个堆大小的1/3或者1/4,两个值设为一样大。
-XX:SurvivorRatio
-XX:SurvivorRatio=8
年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:8,表示Eden:Survivor=8:1,一个Survivor区占整个年轻代的1/10
年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:8,表示Eden:Survivor=8:1,一个Survivor区占整个年轻代的1/10
-XX:NewRatio
-XX:NewRatio=3
设置年轻代(EC+S0C+S1C)和年老代(OC)的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4(jdk1.8,默认2)
设置年轻代(EC+S0C+S1C)和年老代(OC)的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4(jdk1.8,默认2)
-XX:+PrintGCDetails
打印GC的具体信息
更多...
java中查看设置的jvm内存信息
Runtime.getRuntime().maxMemory(); //最大可用内存,对应-Xmx
Runtime.getRuntime().freeMemory(); //当前JVM空闲内存
Runtime.getRuntime().totalMemory(); //当前JVM占用的内存总数,其值相当于当前JVM已使用的内存及freeMemory()的总和
博客推荐
JVM系列三:JVM参数设置、分析
HotSpot VM GC 的种类
0 条评论
下一页