Java基础——Java平台与内存管理

参考Java程序员面试笔试宝典:

目录

1.为什么说Java是平台独立性语言

2.Java平台与其他语言平台有哪些区别

3.JVM加载class文件的原理机制

4.什么是GC

5.Java是否存在内存泄漏问题

6.Java中堆和栈有什么区别



1.为什么说Java是平台独立性语言

平台独立性指的是在一个平台上编写和编译的程序,可在其他平台上运行。

保证Java具有平台独立性的机制是“中间码”和“Java虚拟机(JVM)“

Java程序被编译后生成一个”中间码“,不同硬件平台会装有不同JVM,负责把中间码翻译成硬件平台可以执行的代码。因此JVM不具有平台独立性,而是与硬件平台相关。

解释执行分三步进行:代码装入、代码校验、代码执行。(代码装入由”类加载器完成;被装入代码由字节码校验器检查“)

Java字节码的执行分两种方式:即时编译方式、解释执行方式。通常采用解释执行方式。

即时编译方式指解释器先将字节码编译成机器码,然后再执行该机器码。

解释执行方式指解释器通过每次解释并执行一小段代码来完成Java字节码程序的所有操作。

C/C++中,编译后的代码只能在特定硬件执行,导致没有跨平台特性,但执行效率更高。

问:一个Java程序运行从上到下的环境依次是

答:Java程序、JRE/JVM、操作系统、硬件

2.Java平台与其他语言平台有哪些区别

Java平台是个纯软件平台,可运行在一些基于硬件的平台(如Kinux、Windows等)之上。

Java平台主要包含两个模块:JVM和Java API

JVM是一个虚构出来的计算机,将Java编译生成的中间码转换为机器码并运行,每当一个Java程序运行,都有一个JVM实例,它通过‘调用main()方法启动Java程序,程序结束,JVM才会退出。

Java API是Java为了方便开发人员进行设计的,它提供了很多有用的接口,用Java语言编写,运行在JVM上。

3.JVM加载class文件的原理机制

Java语言是具有动态性的解释性语言,类(class)只有被加载到JVM中才能运行。

加载过程是由类加载器完成的,就是由ClassLoader和它的子类实现的。

类的加载方式分隐式加载和显式加载。

隐式加载指程序使用new等方式创建对象时,隐式调用类的加载器把对应的类加载到JVM中

显式加载指用过直接调用class.forName()方法把所需的类加载到JVM中

一个工程项目有许多的类,程序启动时,只需把需要的类加载到JVM中,其他的类只有被使用时才会被加载,一方面可以加快加载速度,另一方面可节约程序运行时对内存的开销。

Java语言中,每个类或接口都对应一个.class文件,可看作一个个可被动态加载的单元,当部分类产生变化,只需重新编译变化的类,不需重新编译所有的类,加快了编译速度。

类的加载是动态的,保证程序运行的基础类完全加载到JVM中,其他的类需要时再加载。

Java中类可分为3类:系统类、扩展类、自定义类。对应三种类型加载器:

BootStrap Loader —— 负责加载系统类

ExtClassLoader —— 负责加载扩展类

AppClassLoader —— 负责加载应用类

以上三个类通过委托的方式协调工作完成类的加载。就是当有类需要被加载,类加载器会请求父类完成载入工作,父类使用自己的搜索路径来搜索需要被载入的类,如果搜索不到,才会由子类按照其搜索路径来搜索待加载的类。

类加载主要步骤分三步:

1)装载。找到对应class文件并导入

2)链接。分3小步,1.检查。检查待加载类正确性。2.准备。给静态变量分配存储空间。3.解析。符号引用转变为直接引用(可选)

3)初始化。对静态变量和静态代码块执行初始化工作

4.什么是GC

垃圾回收(Garbge Collection,GC)是个非常重要的概念,主要作用是回收程序中不再使用的内存。

C/C++中,开发人员必须非常仔细管理好内存的分配和释放,若忘记或错误释放内存可能导致程序运行不正常甚至崩溃。Java提供了垃圾回收器来自动检测对象的作用域,自动释放不再使用的存储空间,减轻开发人员工作,同时增加系统的安全性和稳定性。

垃圾回收器负责3项任务:分配内存、确保被引用对象不被错误回收、回收不再被引用的对象的内存空间。

垃圾回收器一方面提高了开发人员的生产效率,另一方面对开发人员屏蔽了释放内存的方法,避免错误操作内存,保证程序稳定性。但也带来一些问题,为了实现垃圾回收,垃圾回收器必须跟踪内存使用情况,释放没用对象,之后还要处理堆中碎片,这些操作增加了JVM负担,降低程序执行效率。

对于对象来说,没有变量去引用,就可认为它是垃圾信息,可被回收。只要有一个及一个以上变量引用该对象,就不会被回收。

对垃圾回收器来说,使用有向图记录和管理堆内存中的所有对象,识别哪些对象是”可达的“(有引用对象引用),哪些对象是“不可达的”(没有引用对象引用),所有不可达对象可被垃圾回收。

几种常用的垃圾回收算法:

1)引用计数算法(Reference Counting Collector)

简单但效率较低。主要原理:堆中每个堆中有个引用计数器,对象被引用计数器加1,引用置空或离开作用域减1。这种方法无法解决相互引用问题,JVM没有采用此算法。

2)追踪回收算法(Tracing Collector)

利用JVM维护的对象引用图。从根节点遍历,同时标记遍历到的对象。遍历结束,未被标记的对象就是目前已不被使用的对象,可被回收了。

3)压缩回收算法(Compacting Collector)

把堆中活动的对象移动到堆中一端,会在堆中另外一端留出很大一块空闲区域,相当于对堆中的碎片进行了处理。这种方法可以大大简化消除碎片的工作,但每次处理都会带来性能损失。

4)复制回收算法

把堆分为两个大小相同的区域,任何时刻,只有一个区域被使用,直到这个区域被消耗完为止,此时垃圾回收器中断程序执行,通过遍历把所有活动对象复制到另外一个区域,在复制过程中紧挨布置,从而可消除内存碎片。复制过程结束程序接着运行,直到这块区域使用完,再采用以上方法继续进行垃圾回收。

优点是垃圾回收同时对对象布置也进行了安排,消除内存碎片;缺点是付出了很高的代价,对指定大小的堆来说,需要两倍大小的内存的空间;同时内存调整需要中断当前执行程序,降低了执行效率。

5)按代回收算法(Generational Collector)

对复制回收算法进行了优化,把堆分为两个或多个子堆,每个子堆视为一代。算法运行过程中优先收集”年幼的“对象,如果一个对象经多次收集仍然存活,可将其转移到高一级堆里,减少对其的扫描次数。

5.Java是否存在内存泄漏问题

内存泄漏是指一个不再被程序使用的对象或变量还在内存中占有存储空间。

Java语言引入了垃圾回收机制,是否还存在内存泄漏问题?

在Java语言中,判断一个内存空间是否符合垃圾回收的标准有两个:

第一,给对象赋予空值null,以后再也没被使用过;

第二,给对象赋予了新值,重新分配的内存空间。

一般来说,内存泄漏有两种情况:

一是在堆中申请的空间没有被释放;

二是对象已不再被使用,但仍在内存中保留。

垃圾回收机制可有效解决第一种情况,对于第二种无法保证不再使用的对象会被释放。Java语言的内存泄漏主要指第二种情况。

引起内存泄漏的原因:

1)静态集合类,如HashMap和Vector。如果这些容器为静态,由于它们的生命周期于程序一致,那么容器中对象在程序结束之前不能被释放,造成内存泄漏。

2)各种连接,如数据库连接、网络连接和IO连接。当不再使用数据库,需要调用close()方法释放于数据库的连接。只有连接关闭,垃圾回收器才会回收相应对象。否则,数据库访问结束后,对Connection、Statement或ResultSet不显式关闭,将造成大量对象无法被回收,造成内存泄漏。

3)监听器。Java语言往往会使用监听器,且通常多个,释放对象时记得删除监听器,否则可能导致内存泄漏。

4)变量不合理的作用域。若变量定义范围大于使用范围,可能会造成内存泄漏。若没有及时把对象设置为null,也可能造成内存泄漏。

5)单例模式可能造成内存泄漏。

6.Java中堆和栈有什么区别

Java语言中,堆和栈都是内存中存放数据的地方。

栈内存主要存放基本数据类型与引用变量。

栈内存管理通过压栈和弹栈操作完成,有函数调用时,压栈创建新的栈帧,函数调用结束则通过弹栈释放栈帧。

堆内存存放运行时创建的对象。

一般是通过new关键字创建出来的对象存放在堆内存。JVM是基于堆栈的虚拟机,每个Java程序运行在一个单独的JVM实例上,每一实例唯一对应一个堆,一个Java程序的多个线程运行在同一个JVM实例上,这些线程间共享堆内存。因此多线程在访问堆中数据需要对数据进行同步。

在堆中创建一个数组或对象后,还可以在栈中定义一个特殊变量,让栈中这个变量的取值等于数组或对象在堆中的首地址,栈中这个变量就成为数组或对象的引用变量。引用变量相当于为数组或对象起的一个名称,在程序中可用栈中的引用变量访问堆中的数组或对象。这就是Java中引用的用法。

从堆和栈的功能及作用来比较,堆主要用来存放对象,栈主要执行程序。相较于堆,栈的存取速度更快,但栈的大小和生存期必须是确定的,因此缺乏一定的灵活性。而堆可以在运行时动态分配内存,生存期不用告诉编译器,这也导致存取速度缓慢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值