1.电脑怎样认识我们编写的Java代码
- 首先先了解电脑是二进制的系统,他只认识 01010101
- 比如我们经常要编写 HelloWord.java 电脑是怎么认识运行的
- HelloWord.java是我们程序员编写的,我们人可以认识,但是电脑不认识
Java文件编译的过程
-
程序员编写的.java文件
-
由javac编译成字节码文件.class(为什么编译成class文件,因为JVM只认识.class文件)
-
在由JVM编译成电脑认识的文件 (对于电脑系统来说文件代表一切)
2. 为什么说java是跨平台语言
- 这个夸平台是中间语言(JVM)实现的跨平台
- Java有JVM从软件层面屏蔽了底层硬件、指令层面的细节让他兼容各种系统
3. Jdk和Jre和JVM的区别
- Jdk包括了Jre和Jvm,Jre包括了Jvm
- Jdk是我们编写代码使用的开发工具包
- Jre 是Java的运行时环境,他大部分都是 C 和 C++ 语言编写的,他是我们在编译java时所需要的基 础的类库
- Jvm俗称Java虚拟机,他是java运行环境的一部分,它虚构出来的一台计算机,在通过在实际的计 算机上仿真模拟各种计算机功能来实现Java应用程序
- 看Java官方的图片,Jdk中包括了Jre,Jre中包括了JVM
4. JVM由哪些部分组成,运行流程是什么?
- JVM包含两个子系统和两个组件: 两个子系统 为Class loader(类装载)、Execution engine(执行引 擎); 两个组件 为Runtime data area(运行时数据区)、Native Interface(本地接口)。
- Class loader(类装载):根据给定的全限定名类名(如:java.lang.Object)来装载class文件到 Runtime data area中的method area。
- Execution engine(执行引擎):执行classes中的指令。
- Native Interface(本地接口):与native libraries交互,是其它编程语言交互的接口。
- Runtime data area(运行时数据区域):这就是我们常说的JVM的内存。
- 流程:首先通过编译器把 Java 代码转换成字节码,类加载器(ClassLoader)再把字节码加载到 内存中,将其放在运行时数据区(Runtime data area)的方法区内,而字节码文件只是 JVM 的一 套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎 (Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要 调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。
5. 什么是JVM字节码执行引擎
- 虚拟机核心的组件就是执行引擎,它负责执行虚拟机的字节码,一般户先进行编译成机器码后执 行。
- "虚拟机"是一个相对于"物理机"的概念,虚拟机的字节码是不能直接在物理机上运行的,需要JVM 字节码执行引擎- 编译成机器码后才可在物理机上执行。
6. 垃圾收集系统
- 程序在运行过程中,会产生大量的内存垃圾(一些没有引用指向的内存对象都属于内存垃圾,因为 这些对象已经无法访问,程序用不了它们了,对程序而言它们已经死亡),为了确保程序运行时的 性能,java虚拟机在程序运行的过程中不断地进行自动的垃圾回收(GC)。
- 垃圾收集系统是Java的核心,也是不可少的,Java有一套自己进行垃圾清理的机制,开发人员无需 手工清理
- 有一部分原因就是因为Java垃圾回收系统的强大导致Java领先市场
7. 堆栈的区别是什么?
注意: 静态变量放在方法区,静态的对象还是放在堆。
8. 深拷贝和浅拷贝
- 浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,
- 深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新 的内存,
- 浅复制:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的 改变。
- 深复制:在计算机中开辟一块新的内存地址用于存放复制的对象。
9. Java会存在内存泄漏吗?为什么?
- 内存泄漏是指不再被使用的对象或者变量一直被占据在内存中。理论上来说,Java是有GC垃圾回 收机制的,也就是说,不再被使用的对象,会被GC自动回收掉,自动从内存中清除。
- 但是,即使这样,Java也还是存在着内存泄漏的情况,java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但 是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。
10. 新生代、老年代、永久代的区别
- 在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。而新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。这样划分的目的是为了使 JVM 能够 更好的管理堆内存中的对象,包括内存的分配以及回收。
- 新生代中一般保存新出现的对象,所以每次垃圾收集时都发现大批对象死去,只有少量对象存活, 便采用了 复制算法,只需要付出少量存活对象的复制成本就可以完成收集。
- 老年代中一般保存存活了很久的对象,他们存活率高、没有额外空间对它进行分配担保,就必须采 用" 标记-清理"或者"标记-整理"算法。
- 永久代就是JVM的方法区。在这里都是放着一些被虚拟机加载的类信息,静态变量,常量等数据。 这个区中的东西比老年代和新生代更不容易回收。
11. Minor GC、Major GC、Full GC是什么
-
Minor GC是新生代GC,指的是发生在新生代的垃圾收集动作。由于java对象大都是朝生夕死的, 所以Minor GC非常频繁,一般回收速度也比较快。(一般采用复制算法回收垃圾)
-
Major GC是老年代GC,指的是发生在老年代的GC,通常执行Major GC会连着Minor GC一起执 行。Major GC的速度要比Minor GC慢的多。(可采用标记清楚法和标记整理法)
-
Full GC是清理整个堆空间,包括年轻代和老年代
12. Minor GC、Major GC、Full GC区别及触发条件
Minor GC 触发条件一般为:
- eden区满时,触发MinorGC。即申请一个对象时,发现eden区不够用,则触发一次 MinorGC。 2. 新创建的对象大小 > Eden所剩空间时触发Minor GC
Major GC和Full GC 触发条件一般为: Major GC通常是跟full GC是等价的
-
每次晋升到老年代的对象平均大小>老年代剩余空间
-
MinorGC后存活的对象超过了老年代剩余空间
-
永久代空间不足
-
执行System.gc()
-
CMS GC异常
-
堆内存分配很大的对象
13. 为什么新生代要分Eden和两个 Survivor 区域?
- 如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被 填满,触发Major GC.老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC 长得多,所以需要分为Eden和Survivor。
- Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选 保证,只有经历15次Minor GC还能在新生代中存活的对象,才会被送到老年代。
- 设置两个Survivor区最大的好处就是解决了碎片化,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满 了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续 的内存空间,避免了碎片化的发生)
14. Java堆老年代( Old ) 和新生代 ( Young ) 的默认比例?
- 默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 --XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。
- 其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,Edem 和俩个Survivor 区域比例 是 = 8 : 1 : 1 ( 可以通过参数 --XX:SurvivorRatio 来设定 ),
- 但是JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总 是有一块 Survivor 区域是空闲着的。