Java基础知识(Java平台与内存管理)

8. Java平台与内存管理

8.1 Java为什么是平台独立性语言

平台独立性是指可以在一个平台上编写和编译程序,而在其他平台运行。使用“中间码”和“JVM”保证平台独立性。java程序被编译后不生成硬件可以运行的代码,而是生成“中间码”,由JVM将“中间码”翻译为硬件可以执行的代码。所以JVM不具有平台独立性,与硬件有关。
解释执行的过程:代码装入—>代码校验—>代码执行,由类装载器装入代码,由字节码校验器进行检查。
java字节码的执行分为两种方式:
1.编译方式:解释器先将字节码编译为机器码,然后再执行该机器码。
2.解释方式:解释器通过每次解释并执行一小段代码完成Java字节码程序的所有操作。

8.2 Java平台与其他语言平台的区别

Java平台主要包括两个模块:JVM和java API。
JVM是一个虚拟出来的计算机,将java编译生成的中间码转换为机器可以识别的编码并运行。有自己完善的硬件架构,如处理器、堆栈、寄存器等。屏蔽与具体操作系统相关的信息,使得java程序只需生成在JVM运行的目标代码(字节码),就可以顺利运行。当一个Java程序运行时都会有一个对应的JVM实例,只有当程序运行结束后,这个JVM才会退出。JVM实例通过调用类的main方法启动一个Java程序,这个main方法必须是公有地,静态的且返回值是void,接收一个字符串数组的参数,只有同时满足才可以作为程序的入口方法。
java API是java为了方便开发人员而设计的,提供很多接口。

8.3 JVM加载class文件的原理机制是什么

Java是一种动态解释性语言,类只有被加载到JVM中才能运行。当运行指定程序时,JVM会将编译生成的.class文件按照需求和一定的规则加载到内存中,并组织成为一个完整的Java应用程序。由类加载器进行加载,类加载器也是一个类,实质上是把类文件从硬盘读取到内存中。

类的加载方式分为隐式和显式加载:
隐式加载:程序使用new方法创建对象时,隐式调用类的加载器把对应的类加载到JVM中。
显示加载:通过直接调用class.forName方法把所需的类加载到JVM中。
在Java中,类的加载是动态的,并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类完全加载到JVM中,其他类在需要的时候才加载。
可以将类分为系统类、扩展类、自定义类,Java对这三种类提供不同的加载器。三种加载器的关系如下:
在这里插入图片描述
在这里插入图片描述
类加载的主要步骤如下:
1.装载:根据查找路径找到相对应的class文件,然后导入。
2.链接:

  • 2.1 检查:检查待加载的class文件的正确性
  • 2.2 准备:给类中的静态变量分配存储空间
  • 2.3 解析:将符号引用转换成直接引用(可选)

3 初始化:对静态变量和静态代码块执行初始化

8.4 GC是什么

垃圾回收的主要作用是回收程序中不再使用的内存。java中的垃圾回收器来自动检测对象的作用域,可自动把不再被使用的存储空间释放掉。主要负责:分配内存、确保被引用对象的内存不被错误的回收以及回收不再被引用的对象的内存空间。
垃圾回收器的优点:
1.将开发人员从释放内存的复杂工作中解脱,提高开发人员的生产效率;
2.对开发人员屏蔽释放内存的方法,保证程序稳定性
垃圾回收期的缺点:
增加JVM负担,降低程序的执行效率。

对对象而言,只要有一个以上的变量引用该对象,该对象就不会被垃圾回收。
对垃圾回收器而言,使用有向图记录和管理堆内存的所有对象,通过这个有向图就可以几十倍那些对象时“可达的”(有引用变量引用),哪些对象是“不可达的”(没有引用变量引用),所有不可达的对象都是可被垃圾回收的。
常用的垃圾回收算法:
1.引用计数算法:
在堆中对每个对象都有一个引用计数器;当对象被引用时,引用计数器+1;当引用被置空或离开作用域时,引用计数-1。该方法无法解决相互引用问题。
2.追踪回收算法:
从根节点开始遍历对象的应用图,同时标记遍历到的对象。当遍历结束后,未被标识的对象就是目前不被使用的对象,可以回收。
3.压缩回收算法:
将堆中活动的对象移动到堆中一端,这样就会在堆中另外一端留出很大的空闲区域,相当于对堆中的碎片进行处理。
4.复制回收算法:
将堆分为两个大小相等的区域,任何时刻只有其中的一个区域使用,直到这个区域被消耗完,此时垃圾回收器中断程序的执行,通过遍历的方法把所有活动的对象复制到另一个区域中,在复制的过程中是紧挨着的,可以消除内存碎片。当复制过程结束后程序会接着运行,直到这块区域被使用完,再使用上面的方法继续进行垃圾回收。
优点:
1.对对象的布置进行安排,消除内存碎片。
缺点:
1.指定大小的堆需要两倍的内存空间;
2.内存调整时要中断当前执行的程序,降低程序的执行效率
5.按代回收算法:
将堆分为两个或多个子堆,每个子堆为一代。运行时优先收集“年幼”对象,如果一个对象经过多次收集仍“存活”,就可以把这个对象转移到高一级堆,减少对其扫描次数。

8.5 Java中是否存在内存泄漏问题

内存泄漏是指一个不再被程序使用的对象或变量在内存中占有存储空间。
在Java中判断一个内存空间是否符合垃圾回收的标准有两个:
1.给对象赋予控制bull,以后再没有使用过
2.给对象赋予新值,重新分配内存空间。
内存泄漏主要有两种情况:
1.在堆中申请的空间没有被释放
2.对象已不再被使用,但还仍然在内存中保留着
垃圾回收机制解决第一种情况;对于第二种情况,垃圾回收机制无法保证不再使用的对象会被释放。
Java中引起内存泄漏的原因:
1、静态集合类:如hashMap或Vector。如果这些容器为静态类,生命周期与程序一致,则容器的对象在程序结束前不能被释放,造成内存泄漏。
2、各种连接,例如数据库连接等。在对数据库进行操作时,首先需要建立与数据库的连接,当不再被使用,需要调用close方法来释放与数据库的连接,只有连接被关闭,垃圾回收器才会回收对应的对象。
3、监听器:在释放对象时没有相应的删除监听器
4、变量不合理的作用域:如果一个变量定义的作用范围大于使用范围,可能会造成内存泄漏
5、单例模式:例如下面的例子:
在这里插入图片描述

8.6 Java中的堆和栈的区别

栈与堆都是存放数据的地方。基本数据类型的变量和对象的引用变量,其内存都是分配在栈上,变量出了作用域就会自动释放。栈内存的管理是通过压栈和弹栈操作完成的,以栈帧为基本单位管理程序的调用关系,当有函数调用时都会通过压栈方式创建新的栈帧,每当函数调用结束后都会通过弹栈的方式释放栈帧。
引用类型的变量的内存分配在堆上或者常量池中,需要通过new等方法进行创建。堆内存用来存放运行时创建的对象,通过new关键字创建的对象都存放在堆内存中。
每个Java程序都运行在一个单独的JVM实例上,每个实例唯一对应一个堆,一个Java程序内的多个线程也就运行在同一个JVM实例上,因此这些线程间共享内存。
堆中产生一个数组或对象后。可以在栈中定义一个特殊的变量,让栈中的变量的取值等于数组或对象在内存中的首地址,栈中的变量就成为数组或对象的引用变量。
堆主要用来存放对象,栈用来存放执行程序。栈的存取速度更快,但栈的大小和生存期是必须确定的。堆可以在运行时动态分配内存,生存期不需要提前告知编译器,存取速度缓慢。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值