美文网首页面试
2017互联网常见面试题

2017互联网常见面试题

作者: 01_小小鱼_01 | 来源:发表于2018-01-31 20:19 被阅读261次

    1. Object 常见方法

    package java.lang;
    public class Object {
        private static native void registerNatives();
        static {
            registerNatives();
        }
    
        public final native Class<?> getClass();
        public native int hashCode();
        public boolean equals(Object obj) {
            return (this == obj);
        }
    
        protected native Object clone() throws CloneNotSupportedException;
        public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
    
        public final native void notify();
        public final native void notifyAll();
        public final native void wait(long timeout) throws InterruptedException;
        public final void wait(long timeout, int nanos) throws InterruptedException {
            if (timeout < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
            if (nanos < 0 || nanos > 999999) {
                throw new IllegalArgumentException(
                                    "nanosecond timeout value out of range");
            }
            if (nanos > 0) {
                timeout++;
            }
            wait(timeout);
        }
    
        public final void wait() throws InterruptedException {
            wait(0);
        }
        protected void finalize() throws Throwable { }
    }
    

    2. 自动装箱

    public static void main(String[] args) {
        int i = 0;
        Integer j = new Integer(0);
        System.out.println(j == i);
        System.out.println(j.equals(i));
    }
    
    // 看看equals的源码
    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }
    true
    true
    

    3. Java 虚拟机 GC 根节点的选择

    Java通过可达性分析来判断对象是否存活。基本思想是通过一系列称为”GC roots”的对象作为起始点,可以作为根节点的是:

    • 虚拟机栈(栈帧中的本地变量表)中引用的对象
    • 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象

    笔者这么理解,作为GC Roots的节点主要在全局性的引用(例如常量或类静态属性)与执行上下文(例如栈帧中的本地变量表)中。
    虚拟机栈、本地方法栈这都是局部变量,某个方法执行完,某些局部使用的对象可以被回收。

    4. 类加载机制

    • 启动类加载器( Bootstrap ClassLoader)
      启动类加载器无法被 java 程序员直接引用, 这个类加载器负责把存放在\lib目录中的, 或者被-Xbootclasspath参数指定路径中的, 并且是被虚拟机识别的类库加载到虚拟机内存中.

    • 扩展类加载器(Extension ClassLoader)
      负责加载在\lib\ext目录中的, 或者被java.ext.dirs系统变量所指定的路径中的所有类库。

    • 应用程序类加载器( Application ClassLoader )
      这个类加载器是ClassLoader 中的 getSystemClassLoader()方法的返回值, 一般称其为系统类加载器, 它负责加载用户类路径( ClassPath )上所指定的类库

    从 java 虚拟机的角度而降, 只存在两种不同的类加载器:
    一个是启动类加载器( Bootstrap ClassLoader ), 这个类加载使用 C++ 语言实现, 是虚拟机自身的一部分;

    另一种是其他所有的类加载器, 他们由 java 语言实现, 独立于虚拟机之外, 并且全部继承自java.lang.ClassLoader

    加载类的寻找范围就是 JVM 默认路径加上Classpath, 类具体是使用哪个类加载器不确定。

    类加载主要步骤

    • 加载 把 class 文件的二进制字节流加载到 jvm 里面
    • 验证 确保 class 文件的字节流包含的信息符合当前 jvm 的要求 有文件格式验证, 元数据验证, 字节码验证, 符号引用验证等
    • 准备 正式为类变量分配内存并设置类变量初始值的阶段, 初始化为各数据类型的零值
    • 解析 把常量值内的符号引用替换为直接引用的过程
    • 初始化 执行类构造器()方法
    • 使用 根据相应的业务逻辑代码使用该类
    • 卸载 类从方法区移除

    双亲委派模型

    除了顶层的启动类加载器之外, 其余的类加载器都应当有自己的父类加载器, 父子关系这儿一般都是以组合来实现。

    工作过程: 如果一个类加载器收到了类加载的请求, 它首先不会自己去尝试加载这个类, 而是把这个请求委派给父类加载器去完成, 最终所有的加载请求都会传送到顶层的启动类加载器中, 只有当父类加载器反馈自己无法完成这个请求时候, 才由子加载器来加载。

    例如类Object,它放在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。

    对于任何一个类, 都需要由加载它的类加载器和这个类本身一同确定其在 java 虚拟机中的唯一性。

    ClassLoader.loadClass()的代码如下,先检查是否已经被加载过,如果没有则parent.loadClass()调用父加载器的loadClass()方法,如果父加载器为空则默认使用启动类加载器作为父加载器。如果父类加载器加载失败,抛出ClassNotFoundException,再调用自己的findClass()方法进行加载。

    另外,如果我们自己实现类加载器,一般是Override复写 findClass方法,而不是loadClass方法。

    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) {
                long t0 = System.nanoTime();
                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.
                    long t1 = System.nanoTime();
                    c = findClass(name); //可以Override该方法
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
    

    参考博客
    1. 2017 互联网校园招聘的一些面试题

    相关文章

      网友评论

        本文标题:2017互联网常见面试题

        本文链接:https://www.haomeiwen.com/subject/hyblzxtx.html