admin 管理员组

文章数量: 1086019

反射,jdk1.8新特性,JVM面试题

反射,jdk1.8新特性,JVM面试题

  • 一.反射
    • 1. 什么是反射机制?反射机制优缺点
    • 2. 反射机制的应用场景
    • 3. Java获取反射的三种方法
  • 二.JDK1.8新特性
    • 1 lambda表达式
    • 2 Optional
  • 三.JVM
    • 1 JVM运行流程
    • 2 说一下 JVM 运行时数据区
    • 3 说一说你对Java堆的理解 ?
    • 4 对Java方法区的理解
    • 5 知道直接内存吗?
    • 6 强引用、软引用、弱引用、虚引用的区别?
    • 7 有没有了解过GC ?
    • 8 垃圾回收器的原理是什么?有什么办法手动进行垃圾回收?
    • 9 讲一下新生代、老年代、永久代的区别
    • 10 对象什么时候可以被垃圾器回收 ?
    • 11 什么是类加载器,类加载器有哪些?
    • 12 说一下类装载的执行过程?
    • 13 双亲委派
    • 14 JVM调优

一.反射

1. 什么是反射机制?反射机制优缺点

JAVA分为编译期运行期.

**编译期:**是指把源码交给编译器编译成计算机可以执行的文件的过程。在 Java 中也就是把 Java 代码编成 class 文件的过程。编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作.

**运行期:**是把=编译后的文件交给计算机==执行,直到程序运行结束。所谓运行期就把在磁盘中的代码放到内存中执行起来。

JAVA反射机制是在运行过程中,对于任意一个类,都可以知道这个类的所有属性和方法;即反射机制指的是程序在运行时能够动态获取自身的信息
对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取信息,动态调用的方法称为java反射机制
反射机制优缺点
缺点 : 性能差,比直接的java代码慢很多
优点 : 灵活性高,运行期类型的判断,动态加载类

2. 反射机制的应用场景

我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关,
例如模块化的开发,通过反射去调用对应的字节码;
动态代理设计模式也采用了反射机制,
还有我们日常使用的 Spring/SpringMVC / Mybatis 等框架也大 量使用到了反射机制

3. Java获取反射的三种方法

1.通过new对象实现反射机制
2.通过路径实现反射机制
3.通过类名实现反射机制

public class CollectionTest {
public static void main(String[] args)  {HashSet<String> hashset = new HashSet<>();hashset.add("世界军事");hashset.add("兵器知识");hashset.add("舰船知识");hashset.add("汉和防务");Iterator iterator = hashset.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}// Java 获取 反射 的三种 方法.Class  aClass = null;//  1.通过 new 对象的方式CollectionTest test = new CollectionTest();try {Class classObject = test.getClass();System.out.println(classObject);//2. 通过类所在路径方式.aClass = Class.forName("com.ZQQQ.study.CollectionTest");//3. 通过类名获取.Class<CollectionTest> testClass = CollectionTest.class;System.out.println(aClass.getName());System.out.println(testClass.getName());} catch (Exception e) {e.printStackTrace();}
}
}

二.JDK1.8新特性

1 lambda表达式

Lambda是一个匿名函数,它允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑
是对函数式接口的另外一种重写形式
函数式接口(接口中只有一个抽象方法)

2 Optional

Optional在Java 8中引入,目的是解决 NullPointerExceptions的问题,Optional是一个包装器类,其中包含对其他对象的引用。在这种情况下,对象只是指向内存位置的指针,并且也可以指向任何内容。从其它角度看,Optional提供一种类型级解决方案来表示可选值而不是空引用。使用Optional类可以避免显式的null值判断(null的防御性检查),避免null导致的NPE(NullPointerException)

参考网址

=1ab6615e-8040-42e5-8db1-ed99325f2e0c&u_asession=01_-JuSsdRFay1_mZ-l7FpIPEG8OPq0ZSwDG4qXevCizjdJqy3iePYEhAz6Y3N5RazX0KNBwm7Lovlpxjd_P_q4JsKWYrT3W_NKPr8w6oU7K-SmGof4t0O91elCv9okkCxFGtJjzcUdNecwu44C77EsWBkFo3NEHBv0PZUm6pbxQU&u_asig=05aDW-yCHahwDpp8Xy5nhr0b0Lkc5IdeaJb494gr6zPdSkeDPD0yqBikIThZ5LOm8oK3tAi-2Hxg2cEK7v0JbDU3oC_QGuZ8zpiNwHbZfDyOLGZah1IjLaA8fHr352sqJLI8f6GA1BiKqI1yv-KQNnyHegBgYVUwazHYGMYPChMcD9JS7q8ZD7Xtz2Ly-b0kmuyAKRFSVJkkdwVUnyHAIJzUcPGRWsLELCBybDq-qTJ0WbNYbQPeHwqO2_mS8tND7vENTe-BCdhmKUxS9kYZDq9e3h9VXwMyh6PgyDIVSG1W_rw0muxJA4-0C2isMJUv3jmIWt_1zFY_I1WBa8sehU0UcVe_nf1_DagNeXHL7bNxNK02DbnOxfsaXFkW0mMaoVmWspDxyAEEo4kbsryBKb9Q&u_aref=odlfzg5tFkg9571oOxroG71Vg90%3D

三.JVM

1 JVM运行流程

1.编译阶段:通过编译器将.java文件编译成字节码文件

2.加载阶段:类加载器(ClassLoad)把字节码文件加载到JVM内存中

3.解释阶段:class字节码经过字节码解释器解释称系统可识别的指令码

4.执行阶段:系统再想硬件设备发送指令码执行操作

2 说一下 JVM 运行时数据区

Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域。
这些区域都有各自的用途,以及创建和销毁的时间,
有些区域随着虚拟机进程的启动而存在,有些区域则是依赖线程的启动和结束而建立和销毁。
Java 虚拟机所管理的内存被划分为如下几个区域
方法区 虚拟机栈 本地方法栈 堆 程序计数器
程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解 析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳 转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成; 为什么要线程计数器?因为线程是不具备记忆功能
== Java 虚拟机栈==(Java Virtual Machine Stacks):每个方法在执行的同时都会在Java 虚拟机栈中创 建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息; 栈帧就是Java虚拟机栈中的下一个单位
本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的; Native 关键字修饰的方法是看不到的,Native 方法的源码大部分都是 C和C++ 的代码
Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实 例都在这里分配内存;
方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的 代码等数据。

详细介绍如下链接
版权声明:本文为CSDN博主「一心猿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:

3 说一说你对Java堆的理解 ?

java堆(Java Heap)是java虚拟机所管理的内存中最大的一块,是被所有线程共享的一块内存区域,在JVM启动时创建。此内存区域的唯一目的就是存放对象实例
在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
java堆是垃圾收集器管理的主要区域,因此也被成为“GC堆”

4 对Java方法区的理解

方法区是所有线程共享内存区域,它用于存储已被Java虚拟机加载的类信息、常量、静态变量、 即时编译器编译后的代码等数据。

5 知道直接内存吗?

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机中定义的内 存区域。
我的理解就是直接内存是基于物理内存和Java虚拟机内存中间内存

图看这篇
版权声明:本文为CSDN博主「目目沐沐」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:

6 强引用、软引用、弱引用、虚引用的区别?

强引用:我们平时new了一个对象就是强引用

例如

Object obj = new Object(); 

即使在内存不足的情况下,JVM 宁愿抛出OutOfMemory错误也不会回收这种对象
软引用:如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会 回收这些对象的内存。

SoftReference<String> softRef = new SoftReference<String>(str); // 软引用
弱引用

弱引用:对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦 发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存

String str=new String("abc");
WeakReference<String> abcWeakRef = new WeakReference<String>(str);

虚引用:如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。

7 有没有了解过GC ?

GC垃圾收集的意思
在JVM中, 有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,
只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,
扫描那些没有被任何引用的对象,并将它们添加到要回收的集合 中,进行回收

8 垃圾回收器的原理是什么?有什么办法手动进行垃圾回收?

对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。
通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。
通过这种方式确定哪些对象是==“可达的”,哪些对象是"不可达的"==。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空 间。

手动执行垃圾回收:System.gc()或Runtime.getRuntime().gc()

,通知GC运行,但是Java语言规范并不保证GC一定会执行.因为gc()函数的作用只是提醒虚拟机:程序员希望进行一次垃圾回收。但是它不能保证垃圾回收一定会进行,而且具体什么时候进行是取决于具体的虚拟机的,不同的虚拟机有不同的对策。可以

9 讲一下新生代、老年代、永久代的区别

在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )
划分的目的是为了使 JVM 能够更好的进行内存的分配以及回收。
新生代主要用来存放新生的对象。在新生代中,保存着大量的刚刚创建的对象,但是大部分的对象都是朝生夕死,所以在新生代中会频繁的进行GC(垃圾回收),所以每次垃圾收集时都发现大批对象死去,只有少量对象存活, 便采用了 复制算法 ,只需要付出少量存活对象的复制成本就可以完成收集。
老年代主要存放应用中生命周期长的内存对象,他们存活率高、没有额外空间对它进行分配担保,。老年代比较稳定,不会频繁的进行MajorGC。而在MaiorGC之前才会先进行一次MinorGc,使得新生的对象进入老年代而导致空间不够才会触发。当无法找到足够大的连续空间分配给新创建的较大对象也会提前触发一次MajorGC进行垃圾回收腾出空间, MajorGC采用了标记—清除算法:首先扫描一次所有老年代里的对象,标记出存活的对象,然后回收没有标记的对象。MajorGC的耗时比较长。因为要扫描再回收。MajorGC会产生内存碎片,当老年代也没有内存分配给新来的对象的时候,就会抛出OOM(Out of
Memory)异常。
永久代指的是永久保存区域。主要存放Class和Meta(元数据)的信息。永久代就是JVM的方法区。在这里都是放着一些被虚拟机加载的类信息,静态变量,常量等数据。 这个区中的东西比老年代和新生代更不容易回收。

10 对象什么时候可以被垃圾器回收 ?

对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收了。
垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。

11 什么是类加载器,类加载器有哪些?

在类加载的过程中,通过一个类的全限定类名来获取描述的该类的二进制字节流,实现这个功能的代码被称为"类加载器".

站在Java虚拟机的角度分为引导类加载器和自定义加载器

站在Java开发人员的角度来看,要分为三层类加载器和用户自定义类加载器:
1 启动类加载器(Bootstrap ClassLoader)用来加载java核心类库,无法被java程序直接引用。
2 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提 供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
3 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。
4 用户自定义类加载器,通过继承 java.lang.ClassLoader类的方式实现

12 说一下类装载的执行过程?

类装载分为以下 5 个步骤:
加载:根据查找路径找到相应的 class 文件然后导入;
验证:检查加载的 class 文件的正确性;
准备:给类中的静态变量分配内存空间;
解析:虚拟机将常量池中的符号引用(理解为标识)替换成直接引用(直接指向内存中的地址)的过程。
初始化:对静态变量和静态代码块执行初始化工作。

13 双亲委派

​ 当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,逐层往上提交,因此所有的加载请求最终都会传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时
才回往下反馈给子类,由子类去完成类的加载。

​ 这样做的好处java中的类随着它的类加载器一起具备了一种带优先级的层次关系保护程序安全

14 JVM调优

JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,
其中最常用的是 jconsole 和 jvisualvm 这 两款视图监控工具。
jconsole:用于对 JVM 中的内存、线程和类等进行监控;
jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。

本文标签: 反射 jdk18新特性 JVM面试题