JVM基础连环问

JVM基础连环问

什么是堆吗?

堆用于存放对象实例,是垃圾收集器管理的主要区域,因此也被称作GC堆。堆可以细分为:新生代(Eden空间、From SurvivorTo Survivor空间)和老年代。

堆栈的区别?

  • 堆的物理地址分配是不连续的,性能较慢;栈的物理地址分配是连续的,性能相对较快。
  • 堆存放的是对象的实例和数组;栈存放的是局部变量,操作数栈,返回结果等。
  • 堆是线程共享的;栈是线程私有的。

了解双亲委派模型吗?

  • 当类载器收到一个类的加载请求时,它首先不会自己尝试去加载它,而是把这个请求委派给父类加载器去完成,这样层层委派,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。

图片

  • 双亲委派模型的具体实现代码在 java.lang.ClassLoader中,此类的 loadClass() 方法运行过程如下:先检查类是否已经加载过,如果没有则让父类加载器去加载。当父类加载器加载失败时抛出 ClassNotFoundException,此时尝试自己去加载。源码如下:
public abstract class ClassLoader {
    // The parent class loader for delegation
    private final ClassLoader parent;

    public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    c = findClass(name);
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

    protected Class<?> findClass(String name) throws ClassNotFoundException {
        throw new ClassNotFoundException(name);
    }
}

为什么需要双亲委派模型呢?

  • 假如没有双亲委派模型而是由各个类加载器自行加载的话,内存里面可能会出现多个相同的类。
  • 比如用户编写了一个java.lang.Object的同名类并放在ClassPath中,多个类加载器都去加载这个类到内存中,系统中将会出现多个不同的Object类,那么类之间的比较结果及类的唯一性将无法保证。

什么是类加载器呢?

  • 类加载器就是加载所有的类的工具,它加载的类在内存中只会存在一份,也就是堆中的Class对象。不可以重复加载
  • Java 文件在经过 Java 编译器编译之后就被转换成 Java 字节码(class 文件)。类加载器负责读取 Java 字节码,并转换成 java.lang.Class类的一个实例。

有哪些类加载器吗?

  • 启动类加载器:用来加载 Java 核心类库,无法被 Java 程序直接引用。
  • 扩展类加载器:它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
  • 系统类加载器:它根据应用的类路径来加载 Java 类。可通过ClassLoader.getSystemClassLoader()获取它。
  • 自定义类加载器:通过继承java.lang.ClassLoader类的方式实现。

怎么判断一个对象是否存活?

  • 引用计数法。给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。

  • 可达性分析。通过GC Root对象为起点,从这些节点向下搜索,搜索所走过的路径叫引用链,当一个对象到GC Root没有任何的引用链相连时,说明这个对象是不可用的。

图片

可以作为GC Roots的对象有哪些呢?

  • 虚拟机栈中引用的对象
  • 本地方法栈中Native方法引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
posted @ 2022-08-25 00:03  Faetbwac  阅读(28)  评论(0编辑  收藏  举报