jvm一些知识点

jvm:

谈谈对java的理解?
1.平台无关性
2.GC(垃圾回收机制)
3.语言特性
4.面向对象
5.类库
6.异常处理

compoile Once,Run Anywhere(一次打包,到处运行)如何实现?
编译时 (javac cc/ccc/bb.java) 
编译后,行成一个 xxx.class文件
 
运行时 (java cc.ccc.bb)

如何查看 bb.class 中的内容
javap -help 可以查看一下指令

对 .class 文件进行反编译
javap -c cc.ccc.bb  

流程:
   使用 javac编译 .java 的文件 生成字节码 .class 文件
   然后由JVM进行解析,转换成特定平台的执行指令(JVM For linux
   ,JVM for win,JVM for IOS)
   
为什么JVM不直接将源码解析成机器码去执行?
 如果用源码去各个平台,在编译前都需要去检查
 语法的错误,会做很多重复的事情
 
JVM如何加载.class文件?
 JVM是内存中的虚拟机
 java虚拟机:
 Class Loader : 依据特定格式,加载class文件到内存
 Execution Engine : 对命令进行解析
 Native Interface : 融合不同开发语言的原生库为java所用
 Runtime Data Area:JVM内存空间结构模型


谈谈反射?
  java 反射机制是在运行状态中,对于任意一个类
  ,都能够知道这个类的所有属性和方法,对于任意
  一个对象,都能够调用他的任意方法和属性,这种
  这种动态获取信息以及动态调用对象方法的功能
  称为java反射机制
  
  反射例子:
  Class rc = Class.foName("类的全路径");  --获取一个类对象
  rc.newInstance();   -- 创建一个实例
  rc.getName();  --名字
  
  Method[] getHello = rc.getDeclaredMethods(); --获取类中的方法
  Object aa = getHello.invoke(Object,"参数"); --调用方法
  使用私有的方法前,必须加  getHello.setAccessible(true)
   
   Fields name = rc.getDeclaredFields(); --获取属性
   name.set() ---设置属性   使用私有属性前 name.setAccessible(true)
   
类从编译到执行的过程?
  1.编译器将 aa.java 源文件 编译为 aa.class字节码文件
  2.ClassLoader 将字节码转换为JVM 中的Class<aa>对象
  3.JVM利用Class<aa>对象实例化为aa对象
  
谈谈ClassLoader?
 ClassLoader 在JAVA中有着非常重要的作用,它主要工作
 在Class装载的加载阶段,其主要作用是从系统外部获得
 Class二进制数据流,他是JAVA的核心组件,所有的Class
 都是由ClassLoader进行加载的,ClassLoader 负责通过
 将Class文件里的二进制数据流装载进系统,然后交给JAVA
 虚拟机进行连接、初始化等操作。
 
ClassLoader的种类?
 BootStrapClassLoader : C++编写,加载核心库 java.*
 ExtClassLoader : Java编写,加载扩展库 javax.*
 AppClassLoader : Java编写,加载程序所在目录
 自定义ClassLoader : Java编写,
 (关键函数 findClass (用于寻找类文件,返回的是一个字节数组); 
             defineClass())
 
谈谈类加载的双亲委派机制?
加载类的过程 首先 由自定义的ClassLoader 去看是否曾经
加载过(通过findLoadedClass方法加载,然后判断是否为空),
如果有就加载,没有就向上,App -> Ext -> BootStrap,
如果都没有加载过,则由 BootStrap 去指定的路径下进行加载,
如果没有 依次向下 ->Ext  -> App -> 自定义

为什么要使用双亲委派机制去加载类?
1.避免多份同样的字节码的加载
2.避免恶意修改源代码

类的加载方式?
隐式:new
显式加载:loadClass,forName 等


类的装载过程?
加载:
  通过ClassLoader加载class文件字节码,生成Class对象
链接:
  校验:检查加载的class的正确性和安全性
  准备:为类变量(static)分配存储空间并设置类变量初始值
  解析:JVM将常量池内的符号引用转换为直接引用
初始化:
  执行类变量赋值和静态代码块
  

loadClass 和 forName 的区别
Class.forName 得到的class是已经初始化完成的
(Class r = Class.forName("com.aa");)
Class.loadClass 得到的class是还没有链接的 (没有链接与进行初始化)
(ClassLoader cl = aa.class.getClassLoader();)
作用:
  1.在加载 jdbc 连接的时候用 Class.forName();
    因为,com.mysql.jdbc.Driver 中有一段静态代码
    需要初始化,所以要用forName才行,才能获得Driver
    
  2.spring ioc 加载的时候,是lazy加载,为了加快加载速度
    所以采用Class.loadClass(),在实际使用的时候在加载

扫描二维码关注公众号,回复: 5355719 查看本文章


jdk 8  java内存模型
 从线程的角度看:
    线程私有的:
        程序计数器(是逻辑计数器,不会发生内存泄露);
          (当前线程所执行的字节码行号指示器)
          (改变计数器的值来选取下一条需要执行的字节码指令)
          (和线程是一对一的关系即“线程私有”)
        虚拟机栈:
          (java方法执行的内存模型)
          (包含多个栈帧 
                包含:
                    局部变量表:包含方法执行过程中的所有变量,为操作数栈提供必要的数据支撑
                    操作数栈,
                    动态连接,
                    返回地址)
        本地方法栈:
           (与虚拟机栈类似,主要作用于标注了native的方法)
    所有线程共享的:
        metaSpace(类加载信息OOM),
        常量池,
        堆
    
递归为什么会引发java.lang.StackOverflowError异常?
递归过深,栈帧(每调用一个方法,就会行成一个栈帧压入虚拟机栈中)数超过出虚拟栈深度

元空间(metaSpace)与永久代(permGen)的区别
(jdk 8)              (jdk 7 以前)
首先,这两个都是用来存储Class 相关信息
元空间使用本地内存,而永久代使用的JVM的内存

MetaSpace 相比PermGen的优势
 字符串常量池存在永久代中,容易出现性能问题和内存溢出
 类和方法的信息大小难易确定,给永久代的大小指定带来困难
 永久代会为GC带来不必要的复杂性


java堆(heap) 
   对象实例的分配区域
   GC管理的主要区域


JVM三大性能调优参数-Xms -Xmx -Xss的含义
  -Xss:规定了每个线程虚拟机栈(堆栈)的大小
       (一般256就足够了)
  -Xms:堆的初始值
  -Xmx:堆能达到的最大值
  (一般这两个值设置的是相同的,避免扩容时候
    发生内存抖动,影响程序运行时的稳定性)
  
Java内存模型中堆和栈的区别--内存分配策略
  内存分配策略:
   静态存储:编译时确定每个数据目标在运行时的存储空间需求
   栈式存储:数据区需求在编译时未知,运行时模块入口前确定
   堆式存储:编译时或运行时模块入口都无法确定,动态分配
   
   堆与栈的区别:
   管理方式:栈自动释放,堆需要GC
   空间大小:栈比堆小
   碎片相关:栈产生的碎片远小于堆
   分配方式:栈支持静态和动态分配,而堆仅支持动态分配
   效率:栈的效率比堆高
   
不同版本之间的intern()方法的区别 - JDK6 VS JDK6+
   String s = new String("hello");
   s.intern();
   JDK6: 若存在常量池,则引用,若不存在,则将其添加
           到常量池,并返回引用
           
   JDK6+:若在常量池,则引用,否则在java堆中是否存在
           若存在,则将堆中对象添加常量池,返回引用
           ,否则,在常量池创建,返回引用
           

 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/wjxhhh123/article/details/87969081