java jvm的知识详细介绍

java jvm 详解:

关于jvm的相关知识

一、堆内存和栈内存

1、jvm中的栈内存主要存储的是基本类型的变量和对象的引用

2、jvm中的堆内存主要存储的是用new来创建的对象和数组,可变长字符串(StringBuilder和StringBuffered)都是存储在堆内存的

使用堆的优点是动态分配存储空间,更灵活,但缺点是由于要动态分配内存,所以存储速度较慢;而使用栈速度就比较快,也可以实现数据的共享,但缺点是栈中的数据大小和生存期是必须确定的,缺乏灵活性

3、静态存储分配是存储静态变量和静态代码块的

二、jvm的认识

jvm即java虚拟机,它屏蔽了与具体操作系统平台相关的信息,使java程序只生成在java虚拟机上运行的目标代码(字节码),这样就可以实现跨平台运行;

它的原理是:java源文件经过java编译器编译成字节码程序,通过jvm将每一条指令翻译成不同平台的机器码,通过特定的平台运行;

jvm的内存区域主要分为:方法区,jvm栈,堆,本地方法栈,程序计数器

程序计数器:用于记录当前执行到的那个指令,这是唯一一个没有oom情况的区域;

jvm栈:线程私有,每个线程创建的同时都会创建jvm栈,它存放的是当前线程中局部的基本变量,部分返回结果以及stack frame,还有对象的引用地址;

堆:线程共享,用来存储一些对象以及数组;既然共享,就需要加锁,所以导致开销大;

方法区:这个方法区对应的是持久代,它存放的是类的信息(名称、修饰符等等)、类中的静态变量、类中用final定义的常量等等;

本地方法栈:用来支持native方法的执行,用来储存每个native方法的调用状态;

java垃圾回收主要是针对堆和方法区:堆分为新生代和老年代,一般刚刚new出来的对象都会被放入到新生代;而新生代又分为Eden区和两个Survivor区;

垃圾回收的机制就是:首先判断出哪些对象是垃圾,即不再被使用,然后利用相应的算法(标记-清除算法、复制算法、标记-整理算法、分代收集算法)对垃圾进行回收;

1、标记-清除算法:

分两个阶段,标记阶段和清除阶段,首先标记出需要被回收的对象,然后再回收标记对象所占有的空间;

它的实现比较简单,但是缺点就是容易产生内存碎片,导致后续需要为大对象分配空间时找不到足够的内存而提前触发一次新的垃圾回收动作;

2、复制算法:

复制算法为了解决标记-清除算法的缺点,它将内存按容量划分成大小相等的两块区域,每次只使用其中的一块;当一块用完了之后,就将还存活着的对象复制到另外一块区域,然后再把使用过的那一块区域清理掉,这样就不容易出现碎片;

解决了内存碎片的问题,但是缺点是将使用的内存减少到了原来的一半,并且复制的效率跟存活下来的对象数量有关,当数量很大时,效率大大降低;

3、标记-整理算法

为了解决复制算法的缺陷,标记-整理算法诞生,标记阶段也跟标记-清除算法一样,先把需要回收的对象标记出来,但是它不是直接回收,而是将存活的对象都向另一边移动,然后清理掉边界以外的内存;

4、分代收集算法

这是目前用的最多的一个算法,它的核心思想是根据对象的存活周期将内存划分为若干个不同的区域,一般情况下将堆区划分为新生代和老年代,老年代的特点就是每次垃圾回收时需要回收的对象比较少,而新生代的就比较多,所以采取不一样的算法;

目前新生代大部分采用的是复制算法,但实际上并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。

而由于老年代的特点是每次回收都只回收少量对象,一般使用的是标记-整理(Mark-Compact)算法。

注意,在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量和无用的类。

那么我们怎么确定什么对象是“垃圾”呢?

方法一、引用计数法:

在java中是通过引用来和对象进行关联的,也就是说如果要操作对象,必须通过引用来进行。那么很显然一个简单的办法就是通过引用计数来判断一个对象是否可以被回收。不失一般性,如果一个对象没有任何引用与之关联,则说明该对象基本不太可能在其他地方被使用到,那么这个对象就成为可被回收的对象了。这种方式成为引用计数法。

优点:实现简单,效率高

缺点:无法解决循环引用的问题

方法二、可达性分析法:

该方法的基本思想是通过一系列的“GC Roots”对象作为起点进行搜索,如果在“GC Roots”和一个对象之间没有可达路径,则称该对象是不可达的,不过要注意的是被判定为不可达的对象不一定就会成为可回收对象。被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。

哪些对象可以成为GC Roots呢?

1.jvm栈(栈帧中的本地变量表)中引用的对象。
2.方法区中类静态属性引用的对象。
3.方法区中常量引用的对象
4.本地方法栈中JNI(即一般说的Native方法)引用的对象。

对于程序员来说,我们也可以通过一些方法来减少GC开销:

1、不要显示地调用System.gc()方法

2、尽量减少临时对象的使用

3、对象不用的时候显示地设置为null

4、尽量使用StringBuilder来代替String累加字符串

5、能用基本类型的变量(int long),就不要用对象(Integer、Long)

6、尽量少使用静态对象变量

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • 详谈jvm--Java中init和clinit的区别

    init和clinit区别 ①init和clinit方法执行时机不同 init是对象构造器方法,也就是说在程序执行 new 一个对象调用该对象类的 constructor 方法时才会执行init方法,而clinit是类构造器方法,也就是在jvm进行类加载-–验证--解析-–初始化,中的初始化阶段jvm会调用clinit方法. ②init和clinit方法执行目的不同 init is the (or one of the) constructor(s) for the instance, and

  • Java 虚拟机(JVM)之基本概念详解

    1.类加载子系统:负责从文件系统或者网络中加载Class信息,加载的信息存放在一块称之为方法区的内存空间. 2.方法区:就是存放类信息.常量信息.常量池信息.包括字符串字面量和数字常量等.方法区是辅助堆栈的块永久区,解决堆栈信息的产生,是先决条件. 3.Java堆:再java虚拟机启动的时候建立Java堆,它是java程序最主要的内存工作区域,几乎所有的对象实例都存放到Java堆中,堆空间是所有线程共享的.堆解决的是数据存储问题,即数据怎么放.放在哪儿. 4.直接内存:Java的NIO库允许Ja

  • java jvm的知识详细介绍

    java jvm 详解: 关于jvm的相关知识 一.堆内存和栈内存 1.jvm中的栈内存主要存储的是基本类型的变量和对象的引用 2.jvm中的堆内存主要存储的是用new来创建的对象和数组,可变长字符串(StringBuilder和StringBuffered)都是存储在堆内存的 使用堆的优点是动态分配存储空间,更灵活,但缺点是由于要动态分配内存,所以存储速度较慢:而使用栈速度就比较快,也可以实现数据的共享,但缺点是栈中的数据大小和生存期是必须确定的,缺乏灵活性 3.静态存储分配是存储静态变量和静

  • Java 反射机制知识详细介绍及总结

    本篇将从以下几个方面讲述反射的知识: class 的使用 方法的反射 构造函数的反射 成员变量的反射 一.什么是class类 在面向对象的世界里,万物皆对象.类是对象,类是java.lang.Class类的实例对象.另外class类只有java虚拟机才能new出来.任何一个类都是Class 类的实例对象.这实例对象有三种表达方式: public class User{ } public class ClassTest{ User u=new User(); //方式1: Class c1=Use

  • java并发之ArrayBlockingQueue详细介绍

    java并发之ArrayBlockingQueue详细介绍 ArrayBlockingQueue是常用的线程集合,在线程池中也常常被当做任务队列来使用.使用频率特别高.他是维护的是一个循环队列(基于数组实现),循环结构在数据结构中比较常见,但是在源码实现中还是比较少见的. 线程安全的实现 线程安全队列,基本是离不开锁的.ArrayBlockingQueue使用的是ReentrantLock,配合两种Condition,实现了集合的线程安全操作.这里稍微说一个好习惯,下面是成员变量的声明. pri

  • java数据类型与二进制详细介绍

    java数据类型与二进制详细介绍 在java中 Int 类型的变量占 4个字节 Long 类型的变量占8个字节 一个程序就是一个世界,变量是这个程序的基本单位. Java基本数据类型 1.        整数类型 2.        小数(浮点数)类型 3.        布尔类型 4.        字符类型 整数类型 整数类型可以表示一个整数,常用的整数类型有:byte,short,int,long Byte  一个字节  -128到127 注:0有两个表示0000 0000正零  1000

  • Java类加载基本过程详细介绍

    Java类加载基本过程详细介绍 基本过程: 根据类的全限定名称加载定义类的二进制字节流. 将字节流代表的静态存储结构转化为方法区的运行时数据结构 内存中生成一个代表这个类的java.lang.Class对象,作为方法去这个类的各种数据访问入口 数组类本身不通过类加载器创建,由java虚拟机直接创建,数组类的元素类型由类加载器加载. 数组类的元素类型:数组去掉所有维度后的类型, 文件格式验证: 0xCAFEBABY 魔数开头: 主次版本号当前虚拟机可处理: 常量类型: 索引执行类型: utf8编码

  • java 注解的基础详细介绍

    java 注解的基础详细介绍 前言 注解是Java引入的一项非常受欢迎的补充,它提供了一种结构化的,并且具有类型检查能力的新途径,从而使得程序员能够为代码加入元数据,而不会导致代码杂乱且难以阅读.使用注解能够帮助我们避免编写累赘的部署描述文件,以及其他生成的文件. 注解的语法比较简单,除了@符号的使用之外,它基本与java固有的语法一致.但由于java源码中提供的内置注解很少,所以大部分同学对注解都不是很了解,虽然我们都接触过,比如java内置的几种注解: @Override,表示当前的方法定义

  • Java多线程的用法详细介绍

    Java多线程的用法详细介绍 最全面的Java多线程用法解析,如果你对Java的多线程机制并没有深入的研究,那么本文可以帮助你更透彻地理解Java多线程的原理以及使用方法. 1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例.Thread构造函数: public Thread( ); publi

  • Java中ArrayList类详细介绍

    Java中ArrayList类详细介绍 ArrayList是一个可变长度数组,它实现了List接口,因此它也可以包含重复元素和Null元素,也可以任意的访问和修改元素,随着向 ArrayList 中不断添加元素,其容量也自动增长.不过ArrayList是非同步(同步的意思是如果多个线程同时访问一个实例,任何一个线程对实例做了修改之后,其他线程所访问到的实例应该是修改过的最新的实例)的, 我们经常使用List list = Collections.synchronizedList(new Arra

  • Java classloader和namespace详细介绍

    Java classloader和namespace详细介绍 Java虚拟机通过装载.连接和初始化一个JAVA类型,使该类型可以被正在运行的JAVA程序所使用.其中,装载就是把二进制形式的JAVA类型读入JAVA虚拟机中.连接就是把这种已经读入虚拟机的二进制形式的类型数据合并到虚拟机的运行时状态中去.连接阶段分为三个步骤-验证.准备和解析.验证确保了JAVA类型数据格式正确并适于JAVA虚拟机使用.准备负责为该类分配它所需的内存,比如为它的类变量分配内存.解析把常量池中的符号引用转换为直接引用,

  • Java规则引擎easy-rules详细介绍

    目录 简介 开始使用 引入依赖 定义规则 使用注解定义规则 使用RuleBuilder定义规则 组合规则 规则优先级 Rules API 定义事实 定义规则引擎 创建规则引擎 规则引擎参数 定义规则监听器 定义规则引擎监听器 表达式语言(EL)支持 EL提供者注意事项 通过编程的方式定义规则 通过规则描述文件定义规则 规则定义中的错误处理 实际栗子 最近在思考一个基于规则进行挑选的技术重构,想通过规则引擎进行实现,借着这个机会正好可以详细了解一下规则引擎.本篇文章将会详细介绍规则引擎easy-r

随机推荐