Android 高频面试必问之Java基础,2021最新Android中级面试题目汇总解答

本文详细介绍了Java面试中常见的基础知识,包括方法区的演变,从永久代到元空间,直接内存的使用,以及类加载器的工作原理。讨论了Java的垃圾回收机制和几种垃圾回收算法,如标记-清除、复制、标记-整理和分代收集。此外,还涵盖了Java中的成员变量与局部变量的区别,方法重写和重载的概念,以及传递和引用传递的差异。最后,文章讨论了equals与hashCode的关系,接口与抽象类的异同,并对HashMap的实现进行了深入剖析,包括JDK8中的红黑树优化。同时,还介绍了ConcurrentHashMap的CAS操作及其在并发控制中的作用,以及乐观锁和悲观锁的区别。
摘要由CSDN通过智能技术生成
4.5 方法区

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

在 HotSpot JVM 中,永久代(永久代实现方法区)中用于存放类和方法的元数据以及常量池,比如Class和Method。每当一个类初次被加载的时候,它的元数据都会放到永久代中。永久代是有大小限制的,因此如果加载的类太多,很有可能导致永久代内存溢出,为此我们不得不对虚拟机做调优。

后来HotSpot放弃永久代(PermGen),jdk1.7版本中,HotSpot已经把原本放在永久代的字符串常量池、静态变量等移出,到了jdk1.8,完全废弃了永久代,方法区移至元空间(Metaspace)。比如类元信息、字段、静态属性、方法、常量等都移动到元空间区。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。

常用的JVM调参如下表:

| 参数 | 作用描述 |

| — | — |

| -XX:MetaspaceSize | 分配给Metaspace(以字节计)的初始大小。如果不设置的话,默认是20.79M,这个初始大小是触发首次 Metaspace Full GC 的阈值,例如 -XX:MetaspaceSize=256M |

| -XX:MaxMetaspaceSize | 分配给Metaspace 的最大值,超过此值就会触发Full GC,此值默认没有限制,但应取决于系统内存的大小。JVM会动态地改变此值。但是线上环境建议设置,例如-XX:MaxMetaspaceSize=256M |

| -XX:MinMetaspaceFreeRatio | 最小空闲比,当 Metaspace 发生 GC 后,会计算 Metaspace 的空闲比,如果空闲比(空闲空间/当前 Metaspace 大小)小于此值,就会触发 Metaspace 扩容。默认值是 40 ,也就是 40%,例如 -XX:MinMetaspaceFreeRatio=40 |

| -XX:MaxMetaspaceFreeRatio | 最大空闲比,当 Metaspace 发生 GC 后,会计算 Metaspace 的空闲比,如果空闲比(空闲空间/当前 Metaspace 大小)大于此值,就会触发 Metaspace 释放空间。默认值是 70 ,也就是 70%,例如 -XX:MaxMetaspaceFreeRatio=70 |

运行时常量池 运行时常量池是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表,用于存放编译期间生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。 方法区中存放:类信息、常量、静态变量、即时编译器编译后的代码。常量就存放在运行时常量池中。 当类被 Java 虚拟机加载后, .class文件中的常量就存放在方法区的运行时常量池中。而且在运行期间,可以向常量池中添加新的常量。如String类的intern()方法就能在运行期间向常量池中添加字符串常量。

4.6 直接内存

直接内存并不是虚拟机运行时数据区的组成部分,在 NIO 中引入了一种基于通道和缓冲的 IO 方式。它可以通过调用本地方法直接分配Java虚拟机之外的内存,然后通过一个存储在堆中的DirectByteBuffer对象直接操作该内存,而无须先将外部内存中的数据复制到堆中再进行操作,从而提高了数据操作的效率。

由于直接内存并非Java虚拟机的组成部分,因此直接内存的大小不受 Java 虚拟机控制,但既然是内存,如果内存不足时还是会抛出OutOfMemoryError异常。

下面是直接内存与堆内存的一些异同点:

  • 直接内存申请空间耗费更高的性能;

  • 直接内存读取 IO 的性能要优于普通的堆内存。

  • 直接内存作用链: 本地 IO -> 直接内存 -> 本地 IO

  • 堆内存作用链:本地 IO -> 直接内存 -> 非直接内存 -> 直接内存 -> 本地 IO

服务器管理员在配置虚拟机参数时,会根据实际内存设置-Xmx等参数信息,但经常忽略直接内存,使得各个内存区域总和大于物理内存限制,从而导致动态扩展时出现OutOfMemoryError异常。

5,简单介绍下Java的类加载器

Java的类加载器可以分为BootstrapClassLoader、ExtClassLoader和AppClassLoader,它们的作用如下。

  • BootstrapClassLoader:Bootstrap 类加载器负责加载 rt.jar 中的 JDK 类文件,它是所有类加载器的父加载器。Bootstrap 类加载器没有任何父类加载器,如果调用String.class.getClassLoader(),会返回 null,任何基于此的代码会抛出 NUllPointerException 异常,因此Bootstrap 加载器又被称为初始类加载器。

  • ExtClassLoader:Extension 将加载类的请求先委托给它的父加载器,也就是Bootstrap,如果没有成功加载的话,再从 jre/lib/ext 目录下或者 java.ext.dirs 系统属性定义的目录下加载类。Extension 加载器由 sun.misc.Launcher$ExtClassLoader 实现。

  • AppClassLoader:Java默认的加载器就是 System 类加载器,又叫作 Application 类加载器。它负责从 classpath 环境变量中加载某些应用相关的类,classpath 环境变量通常由 -classpath 或 -cp 命令行选项来定义,或者是 JAR 中的 Manifest 的 classpath 属性,Application 类加载器是 Extension 类加载器的子加载器。

类加载会涉及一些加载机制。

  • 委托机制:加载任务委托交给父类加载器,如果不行就向下传递委托任务,由其子类加载器加载,保证Java核心库的安全性。

  • 可见性机
    :子类加载器可以看到父类加载器加载的类,而反之则不行。

  • 单一性原则:父加载器加载过的类不能被子加载器加载第二次。

6,谈一下Java的垃圾回收,以及常用的垃圾回收算法。

Java的内存管理主要涉及三个部分:堆 ( Java代码可及的 Java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值