面试系列二:精选大数据面试真题JVM专项-附答案详细解析 (二)

简介: 精选大数据面试真题JVM专项-附答案详细解析

第二题:类加载相关(新浪微博)


问:jvm加载类的过程主要有哪些,具体怎么加载?


答:


简答:类加载过程即是指JVM虚拟机把.class文件中类信息加载进内存,并进行解析生成对应的class对象的过程。分为五个步骤:加载 -> 验证 -> 准备 -> 解析 -> 初始化。加载:将外部的 .class 文件加载到Java虚拟机中;验证:确保加载进来的 calss 文件包含的额信息符合 Java 虚拟机的要求;准备:为类变量分配内存,设置类变量的初始值;解析:将常量池内的符号引用 转为 直接引用;初始化:初始化类变量和静态代码块。


精答前方预警,内容较长,做好准备


一个Java文件从编码完成到最终执行,一般主要包括两个过程:编译、运行


  • 编译:即把我们写好的java文件,通过javac命令编译成字节码,也就是我们常说的.class文件。


  • 运行:则是把编译生成的.class文件交给Java虚拟机(JVM)执行。


而我们所说的类加载过程即是指JVM虚拟机把.class文件中类信息加载进内存,并进行解析生成对应的class对象的过程。


  • 类加载过程


举个简单的例子来说,JVM在执行某段代码时,遇到了class A, 然而此时内存中并没有class A的相关信息,于是JVM就会到相应的class文件中去寻找class A的类信息,并加载进内存中,这就是我们所说的类加载过程。


由此可见,JVM不是一开始就把所有的类都加载进内存中,而是只有第一次遇到某个需要运行的类时才会加载,且只加载一次。


  • 类加载


类加载的过程主要分为三个部分:加载、链接、初始化。


而链接又可以细分为三个小部分:验证、准备、解析。


  • 加载


简单来说,加载指的是把class字节码文件从各个来源通过类加载器装载入内存中。


这里有两个重点:


字节码来源:一般的加载来源包括从本地路径下编译生成的.class文件,从jar包中的.class文件,从远程网络,以及动态代理实时编译


类加载器:一般包括启动类加载器,扩展类加载器,应用类加载器,以及用户的自定义类加载器。


注:为什么会有自定义类加载器?


一方面是由于java代码很容易被反编译,如果需要对自己的代码加密的话,可以对编译后的代码进行加密,然后再通过实现自己的自定义类加载器进行解密,最后再加载。


另一方面也有可能从非标准的来源加载代码,比如从网络来源,那就需要自己实现一个类加载器,从指定源进行加载。


  • 验证


主要是为了保证加载进来的字节流符合虚拟机规范,不会造成安全错误。


包括对于文件格式的验证,比如常量中是否有不被支持的常量?文件中是否有不规范的或者附加的其他信息?


对于元数据的验证,比如该类是否继承了被final修饰的类?类中的字段,方法是否与父类冲突?是否出现了不合理的重载?


对于字节码的验证,保证程序语义的合理性,比如要保证类型转换的合理性。


对于符号引用的验证,比如校验符号引用中通过全限定名是否能够找到对应的类?校验符号引用中的访问性(private,public等)是否可被当前类访问?


  • 准备


主要是为类变量(注意,不是实例变量)分配内存,并且赋予初值。


特别需要注意,初值,不是代码中具体写的初始化的值,而是Java虚拟机根据不同变量类型的默认初始值。


比如8种基本类型的初值,默认为0;引用类型的初值则为null;常量的初值即为代码中设置的值,final

static tmp = 456, 那么该阶段tmp的初值就是456。


  • 解析


将常量池内的符号引用替换为直接引用的过程。


两个重点:


符号引用:即一个字符串,但是这个字符串给出了一些能够唯一性识别一个方法,一个变量,一个类的相关信息。


直接引用:可以理解为一个内存地址,或者一个偏移量。比如类方法,类变量的直接引用是指向方法区的指针;而实例方法,实例变量的直接引用则是从实例的头指针开始算起到这个实例变量位置的偏移量。


举个例子来说,现在调用方法hello(),这个方法的地址是1234567,那么hello就是符号引用,1234567就是直接引用。


在解析阶段,虚拟机会把所有的类名,方法名,字段名这些符号引用替换为具体的内存地址或偏移量,也就是直接引用。


  • 初始化


这个阶段主要是对类变量初始化,是执行类构造器的过程。


换句话说,只对static修饰的变量或语句进行初始化。


如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。


如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。


  • 总结


类加载过程只是一个类生命周期的一部分,在其前,有编译的过程,只有对源代码编译之后,才能获得能够被虚拟机加载的字节码文件;在其后还有具体的类使用过程,当使用完成之后,还会在方法区垃圾回收的过程中进行卸载。如果想要了解Java类整个生命周期的话,可以自行上网查阅相关资料,这里不再多做赘述。


第三题:JVM内存相关(云从科技)


问:Java 中会存在内存泄漏吗,请简单描述


答:


理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收也会发生内存泄露。


一个例子就是Hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象。


下面的例子也展示了Java中发生内存泄露的情况:


package com.yuan_more;
import java.util.Arrays;
import java.util.EmptyStackException;
public class MyStack<T> {
    private  T[] elements;
    private int size = 0;
    private static final int INIT_CAPACITY = 16;
    public MyStack(){
        elements = (T[]) new Object[INIT_CAPACITY];
    }
    public void push(T elem){
        ensureCapacity();
    }
    public T pop(){
        if(size == 0){
            throw new EmptyStackException();
        }
        return elements[-- size];
    }
    private void ensureCapacity() {
        if(elements.length == size){
            elements = Arrays.copyOf(elements,2 * size +1);
        }
    }
}


上面的代码实现了一个栈(先进后出(FILO))结构,乍看之下似乎没有什么明显的问题,它甚至可以通过你编写的各种单元测试。


然而其中的pop方法却存在内存泄露的问题,当我们用pop方法弹出栈中的对象时,该对象不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,因为栈内部维护着对这些对象的过期引用(obsolete reference)。


在支持垃圾回收的语言中,内存泄露是很隐蔽的,这种内存泄露其实就是无意识的对象保持。


如果一个对象引用被无意识的保留起来了,那么垃圾回收器不会处理这个对象,也不会处理该对象引用的其他对象,即使这样的对象只有少数几个,也可能会导致很多的对象被排除在垃圾回收之外,从而对性能造成重大影响,极端情况下会引发Disk Paging(物理内存与硬盘的虚拟内存交换数据),甚至造成OutOfMemoryError。


第四题:垃圾回收相关(滴滴出行)


问:知道 GC 吗?为什么要有 GC?


答:


GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃。


Java提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。


要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,注意,只是请求,JVM何时进行垃圾回收具有不可预知性。


垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。


在Java诞生初期,垃圾回收是Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今Java的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得iOS的系统比Android系统有更好的用户体验,其中一个深层次的原因就在于Android系统中垃圾回收的不可预知性。


第五题:JVM内存相关(阿里)


问:Hotspot虚拟机中的堆为什么要有新生代和老年代?


答:


因为有的对象寿命长,有的对象寿命短。应该将寿命长的对象放在一个区,寿命短的对象放在一个区。不同的区采用不同的垃圾收集算法。寿命短的区清理频次高一点,寿命长的区清理频次低一点,提高效率。


所谓的新生代和老年代是针对于分代收集算法来定义的,新生代又分为Eden和Survivor两个区。加上老年代就这三个区。


数据会首先分配到Eden区当中,当然也有特殊情况,如果是大对象那么会直接放入到老年代(大对象是指需要大量连续内存空间的java对象)。当Eden没有足够空间的时候就会触发jvm发起一次Minor GC。新生代垃圾回收采用的是复制算法。


如果对象经过一次Minor GC还存活,并且又能被Survivor空间接受,那么将被移动到Survivor空间当中。并将其年龄设为1,对象在Survivor每熬过一次Minor GC,年龄就加1,当年龄达到一定的程度(默认为15)时,就会被晋升到老年代中了,当然晋升老年代的年龄是可以设置的。如果老年代满了就执行:Full GC, 因为不经常执行,因此老年代垃圾回收采用了标记-整理(Mark-Compact)算法。

相关实践学习
基于MaxCompute的热门话题分析
Apsara Clouder大数据专项技能认证配套课程:基于MaxCompute的热门话题分析
相关文章
|
11月前
|
存储 分布式计算 Hadoop
Hadoop框架解析:大数据处理的核心技术
组件是对数据和方法的封装,从用户角度看是实现特定功能的独立黑盒子,能够有效完成任务。组件,也常被称作封装体,是对数据和方法的简洁封装形式。从用户的角度来看,它就像是一个实现了特定功能的黑盒子,具备输入和输出接口,能够独立完成某些任务。
|
11月前
|
人工智能 分布式计算 DataWorks
多模态数据处理新趋势:阿里云ODPS技术栈深度解析与未来展望
阿里云ODPS技术栈通过MaxCompute、Object Table与MaxFrame等核心组件,实现了多模态数据的高效处理与智能分析。该架构支持结构化与非结构化数据的统一管理,并深度融合AI能力,显著降低了分布式计算门槛,推动企业数字化转型。未来,其在智慧城市、数字医疗、智能制造等领域具有广泛应用前景。
826 6
多模态数据处理新趋势:阿里云ODPS技术栈深度解析与未来展望
|
监控 算法 Java
Java虚拟机(JVM)的垃圾回收机制深度解析####
本文深入探讨了Java虚拟机(JVM)的垃圾回收机制,旨在揭示其背后的工作原理与优化策略。我们将从垃圾回收的基本概念入手,逐步剖析标记-清除、复制算法、标记-整理等主流垃圾回收算法的原理与实现细节。通过对比不同算法的优缺点及适用场景,为开发者提供优化Java应用性能与内存管理的实践指南。 ####
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
544 2
|
存储 Java 开发者
浅析JVM方法解析、创建和链接
上一篇文章《你知道Java类是如何被加载的吗?》分析了HotSpot是如何加载Java类的,本文再来分析下Hotspot又是如何解析、创建和链接类方法的。
662 132
|
人工智能 分布式计算 大数据
MCP、MaxFrame与大数据技术全景解析
本文介绍了 MCP 协议、MaxFrame 分布式计算框架以及大数据基础设施建设的相关内容。MCP(Model Context Protocol)是一种开源协议,旨在解决 AI 大模型与外部数据源及工具的集成问题,被比喻为大模型的“USB 接口”,通过统一交互方式降低开发复杂度。其核心架构包括 Client、Server、Tool 和 Schema 四个关键概念,并在百炼平台中得到实践应用。MaxFrame 是基于 Python 的高性能分布式计算引擎,支持多模态数据处理与 AI 集成,结合 MaxCompute 提供端到端的数据处理能力。
|
机器学习/深度学习 人工智能 JSON
Resume Matcher:增加面试机会!开源AI简历优化工具,一键解析简历和职位描述并优化
Resume Matcher 是一款开源AI简历优化工具,通过解析简历和职位描述,提取关键词并计算文本相似性,帮助求职者优化简历内容,提升通过自动化筛选系统(ATS)的概率,增加面试机会。
1709 18
Resume Matcher:增加面试机会!开源AI简历优化工具,一键解析简历和职位描述并优化
|
存储 搜索推荐 大数据
数据大爆炸:解析大数据的起源及其对未来的启示
数据大爆炸:解析大数据的起源及其对未来的启示
903 15
数据大爆炸:解析大数据的起源及其对未来的启示
|
存储 分布式计算 大数据
大数据揭秘:从数据湖到数据仓库的全面解析
大数据揭秘:从数据湖到数据仓库的全面解析
461 19
|
Java 程序员
面试官的加分题:super关键字全解析,轻松应对!
小米,29岁程序员,通过一个关于Animal和Dog类的故事,详细解析了Java中super关键字的多种用法,包括调用父类构造方法、访问父类成员变量及调用父类方法,帮助读者更好地理解和应用super,应对面试挑战。
269 3

热门文章

最新文章

推荐镜像

更多
  • DNS