Java 底层知识---面试总结

1  对Java的理解

      1. 平台无关性     :一次编译,到处运行

      2 .GC垃圾回收    :垃圾回收机制,不用手动的释放堆内存。

      3. 语言特性    :包括泛型、反射、lambda表达式

      4.面向对象     :封装、继承、多态

      5 .类库    :集合、网络库等

       6.异常处理

2  Compile Once,Run Anywhere  如何实现(平台无关性)

    过程:

         

        编译时:用Javac 指令,将Java源码编译生成字节码,并存入到 .class 文件中

       在终端进行编译如下:Javac  会对源码进行语法检查、校验等

      

      在调用Javac指令后。就将Java文件编译成了Java.class文件。Java.class文件保存的就是Java源码翻译成的二进制字节码,也就是说Java类文件中的属性、方法以及 类中的常量信息都会被分别存储在 .class 文件中,在  .class 文件中还会添加一个共有的静态常量属性  .class, 这个属性记录了类的相关信息,即类型信息,是class的一个实例。

     之后在调用Java 指令运行,该指令让JVM解析字节码文件,并将其加载到内存,最后转换成操作系统能识别的机器码。

     

     通过指令JavaP -C   来对 .class文件进行反编译,查看字节码

  

 

总结

        Java源码首先被编译成字节码,再由不同平台的JVM进行解析,Java语言在不同的平台上运行时不需要重新编译,Java虚拟机在执行字节码文件时,把字节码文件转换成具体平台上的机器指令。

问题:为什么JVM不直接将源码解析成机器码去执行?

       1.如果解析成机器码。那么每次执行的时候都需要各种检查。

         2.兼容性:生成中间的字节码,也可以将别的语言解析成字节码,兼容新更高。

 

 

3   JVM如何加载  . class  文件

         JVM的架构(JVM 是内存中的虚拟机)

               

             Class Loader :  依据特定的格式,加载Class文件到内存。

             Execution Engine(解释器):,对加载到内存中的class文件的命令进行解析。(解析class文件中的字节码,并提交给操作系统去执行)

             Native  Interface(本地接口):融合不同开发语言的原生库为Java所用。

             Runtime Data Area:JVM内存空间结构模型  (所写的程序都会被加载到这里)

 

4   反射

        Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类所有属性和方法;对于任意一个对象,都能够调用他的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。   

    写一个反射的例子   

        1  编写一个robot类 ,包含私有成员变量、公有方法、私有方法。

package Reflect;

public class Robot {
    private String name;
    public void sayHi(String helloSentence){
        System.out.println(helloSentence + " "+name);
    }
    private String throwhello(String tag){
        return "hello "+tag;
    }
}

     2, 用反射来获取robot类中的属性和方法     

package Reflect;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectSample {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //forname 来获取类
        Class rc = Class.forName("Reflect.Robot");
        //newInstance  来创建类的实例
        Robot r=(Robot) rc.newInstance();
        System.out.println("class name is "+rc.getName());
        //getDeclareMethod 获取Robot类声明的throwhello方法.getDeclareMethod 不能获取类继承、实现的方法
        Method gethello=rc.getDeclaredMethod("throwhello", String.class);
        //setAccessible要设置为true, 默认是false,同时因为throwhello方法是私有的
        gethello.setAccessible(true);
        //invoke  执行指定的方法 ,传入的参数分别为实例r,和throwhello方法中需要的参数
        Object str=gethello.invoke(r,"bob");
        System.out.println("gethello result is "+str);
        //getmethod  只能获取类中public的方法  还可以获取继承和实现的方法
        Method sayhi=rc.getMethod("sayHi", String.class);
        //没用定义robot的name  因此输出为welcome null
        sayhi.invoke(r, "welcome");
        //获取类的属性
        Field name=rc.getDeclaredField("name");
        name.setAccessible(true);
        name.set(r,"Alice");
        sayhi.invoke(r,"welcomr");//welcomr Alice
    }
}

    总结: 反射就是把Java类中的一个个成分映射成Java对象。

         1 .  通过Class.forName获取指定路径的Class对象。

         2. 通过newInstance创建对象实例

         3. 通过getMethod可以获取类中的所有public方法(包含继承和实现的方法)

         4 通过getDeclaredMethod 获取指定对象的方法(不包含继承和实现的方法)

          5 通过setAccessible 设置true,获取私有方法。

          6 通过Class.getField 获取类中的字段属性,进行赋值。

          7 通过invoke 执行指定方法。

 

5   Class  Loader

     问题:  类从编译到执行的过程,以Robot类为例?

     1.  编译器将  Robot. java  源文件编译为 Robot.class 字节码文件。(通过Javac指令)

     2. ClassLoader 将字节码转换为JVM中的Class<Robot>对象 (ClassLoader 获取的字节码是以byte数组的形式传递过来的)

     3 JVM 利用Class<Robot>对象实例化为Rotbot 对象。

    ClassLoader  

      ClassLoader 在Java中具有非常重要的作用,它主要工作在Class 装载的加载阶段,其主要作用是从系统外部获得Class二进制数据流。它是Java的核心组件,所有的Class都是有ClassLoader进行加载的,ClassLoader负责通过将Class文件里的二进制数据流装载进系统,然后交给Java虚拟机进行连接、初始化等操作。

ClassLoader 的种类

         1. BootStrapClassLoader: C++ 编写,加载核心库Java.*(自带核心库,由JVM内核实现)

         2 ExtClassLoader: java 编写,加载扩展库Javax.*

        3 AppClassLoader:Java编写,加载程序所在目录

        4 Custom ClassLoader (自定义的): Java编写,定制化加载。

 自定义ClassLoader的实现:

      关键函数:

    

 

 6  ClassLoader的双亲委派机制

        

     问题:ClassLoader双亲委派机制的加载过程:

        1 . 自底而上检查类是否已经被加载

         Custom  ClassLoader -----APP  ClassLoader   ---- Extension Classloader----BootStrap ClassLoader

       2 自下而上尝试加载类

         BootStrap  :加载 jre/lib/rt.jar  或者Xbootclasspath 选项指定的jar包

        Extension:加载jre/lib/ext/*.iar  或者 D Java.ext.dirs 指定目录下的jar包

         APP: j加载ClassPath  或者D Java.calss.path  所指定的目录下的类和jar包

    问题: 为什么要使用双亲委派机制去加载类?

                  避免多份同样字节码的加载

 

7  类的加载方式

      1. 隐私加载:new

       2 .  显示加载:LoadClass   、  forName等  

 

  类的装载过程:(ClassLoader的装载过程)

   1  加载: 通过ClassLoader 加载class文件字节码。生成Class对象

   2  链接:  校验:检查加载的class的正确性和安全性。

                    准备:为类变量分配存储空间并设置类变量的初始值

                    解析:JVM将常量池内的符号引用转化为直接引用。 

   3 初始化  :执行类变量赋值和静态代码块

 

 问题: LoadClass  和forNamede 区别?

      1.Class.forName 得到的class是已经初始化完成的

     2. ClassLoader.LoadClass 得到的class是还没有链接的、

      

  例  :我们首先定义一个带静态代码块的类,我们知道只有类在初始化之后才会执行静态代码块

        

     接着我们使用LoadClass去加载这个类:发现什么都没有打印出来,也就是说类的静态代码块没有被执行

     

    然后我们使用forName来加载这个类,发现静态代码块被执行了,说明完成了初始化

 

  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值