什么是跨平台,Java是如何实现的?平台可以指OS+硬件,所谓跨平台是指用一种语言编写的程序可以在多个系统平台上运行。字节码通过Java虚拟机运行在系统平台上。只要系统能够安装相应的java虚拟机,系统就可以运行java程序编译出的字节码文件,即一次编译,处处运行。JVM是跨平台的吗?不,Java平台的核心是执行字节码的“虚拟机”概念。无论程序运行在哪个硬件或操作系统上,这个字节码都是一样的。虽然Java程序是独立于平台的,但执行它们的Java虚拟机代码却不是。每个操作系统或硬件都有不同的虚拟机。JVM是如何工作的?用户创建aobing.java文件,Java编译器(javac)将该文件编译成aobing.class文件,其中会有一些编译时优化。Java虚拟机加载类并通过解释器或即时编译器将它们编译成机器码。转换后的机器码直接由CPU执行,主流的虚拟机都建立在操作系统之上。什么时候是即时编译器?即时编译器是JRE的一部分,全称是Just-In-TimeCompiler,一般称为JIT,它可以显着提高Java应用程序在运行时的性能。Java编译成字节码后,代码可以通过JVM在很多不同的计算机架构上运行。当开始运行时,JVM中的解释器首先开始工作,逐行将字节码解释成本地机器码,这意味着Java应用程序的执行速度比本地语言应用程序慢。这是背景。为了提高效率,虚拟机引入了JIT技术,通过将热点代码编译成机器码来提高Java程序的性能。JIT编译后的代码存放在方法区。虚拟机如何识别热点代码?目前检测热点代码有两种方式:采样计数器HotSpot采用了计数器方法,它为每个方法准备了两类计数器:方法调用计数器(InvocationCounter)和后沿计数器(BackEdgeCounter)。这两个计数器都有一定的阈值。当计数器超过阈值溢出时,就会触发JIT编译。JDK、JRE和JVMJDK:JDK是(SDK)软件开发工具包的扩展子集,包括用于开发、调试和监视Java应用程序的工具。JRE:JRE被称为Java运行时环境,是JDK的一部分,JDK是一组用于开发Java应用程序的编程工具。Java运行时环境提供了执行Java应用程序的最低要求,它由Java虚拟机(JVM)核心类和核心类库组成。JVM:JVM是一个可以执行字节码的虚拟机。它是Java平台的代码执行组件。什么是幻象引用?幻象引用是虚拟机中定义的“非强”引用级别之一。四种引用的级别从高到低分别是强引用、软引用、弱引用、幻象引用。如果一个对象有强引用,垃圾收集器将永远不会收集它。如果对象只有软引用,内存空间足够,垃圾回收器不会回收;如果内存空间不足,就会回收这些对象的内存。弱引用对象的生命周期较短。在垃圾回收线程扫描其管辖内存区域的过程中,一旦发现只有弱引用的对象,无论当前内存空间是否足够,都会回收其内存。虚引用的对象太脆弱了,我们甚至无法通过虚引用获取到被引用的对象。它唯一的作用是当它指向的对象被回收时,虚引用本身会被加入到引用队列中。用来记录它指向的对象已经被回收了。什么是Java的内存结构、内存模型和对象模型内存结构与运行时数据区有关。内存模型用于屏蔽各种硬件和操作系统的内存访问差异,使Java程序在各种平台上达到一致的并发效果。它是虚拟机的规格之一。对象模型是指java对象在内存中的真实存储(表示)形式。运行时数据区包括哪些部分?存储实例对象的堆。方法区用来存放类信息、常量、静态变量,以及已经被虚拟机加载的即时编译器生成的代码。为了支持多线程程序计数器。用于支持方法的运行虚拟机栈和本地方法栈。面向对象的优点模型类似于现实世界中的对象,更容易理解。由于面向对象具有封装、继承、多态的特点,可以设计出低耦合、高内聚的系统,易于维护、重用和扩展。什么是多态?面向对象的第三大特征之一。它是指同一行为具有多种不同表现形式或形式的能力。作为一种面向对象的语言,Java还可以描述一个事物的多种形式。如果Student类继承了Person类,则Student对象既是Student又是Person。final和finallyfinalize的区别在于final可以修饰类、变量和方法。被修饰的类意味着该类不能被继承,被修饰的方法意味着该方法不能被重写,被修饰的变量意味着该变量是一个不能被重新赋值的常量。finally一般工作在try-catch代码块中。在处理异常的时候,我们通常会将必须执行的代码方法放在finally代码块中,表示无论是否发生异常都会执行该代码块。一般用来存放一些封闭的资源。代码。finalize是属于Object类的一个方法,Object类是所有类的父类。该方法一般由垃圾收集器调用。下面说说JVM加载一个类的过程。JVM中类的加载是由类加载器即ClassLoader及其子类实现的。Java中的类加载器是一个重要的Java运行时系统组件。它负责在运行时查找和加载类文件中的类。由于Java的跨平台特性,Java培训机构编译的Java源程序不是可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保该类已经加载、连接(验证、准备和解析)和初始化。类加载是指将类的.class文件中的数据读取到内存中,通常是创建一个字节数组并将其读取到.class文件中,然后生成与加载的类对应的Class对象。加载完成后,Class对象还没有完成,所以此时的类还不可用。当类加载完成后,进入连接阶段,包括验证、准备(为静态变量分配内存并设置默认初始值)和解析(用直接引用代替符号引用)三个步骤。最后,JVM对类进行初始化,包括:1)如果该类有直接父类,且该类还没有初始化,则先初始化父类;2)如果类中有初始化语句,则依次执行这些初始化语句。什么是类加载器,它们有什么作用?从JDK1.2开始,类加载过程采用双亲委派机制。更好的保证了Java平台的安全性。在这种机制中,JVM自带的Bootstrap是根加载器,其他加载器只有一个父类加载器。类的加载首先请求父类加载器加载,当父类加载器无能为力时,由其子类加载。JVM不提供对Java程序的Bootstrap的引用。根加载器(BootStrap)一般用原生代码实现,负责加载JVM基础核心类库(rt.jar)。扩展加载器(ExtClassLoader)从java.ext.dirs系统属性指定的目录加载类库,它的父加载器是Bootstrap。系统加载器(AppClassLoader)也叫应用类加载器,它的父类是Extension。它是使用最广泛的类加载器。它从环境变量classpath或系统属性java.class.path指定的目录中记录类,并且是用户定义加载器的默认父加载器。用户自定义类加载器(java.lang.ClassLoader的子类)父类是AppClassLoader。加载一个类两次可以加载两次,但是第二次会覆盖第一次。错误和异常有什么区别?error表示一个严重的问题,恢复并非不可能但很困难。例如,内存溢出。指望程序能够处理这样的情况是不可能的。exception表示设计或实现问题。也就是说,它代表了如果程序正确运行就永远不会发生的情况。System.out.println(),什么是System,什么是out,什么是println?System是捆绑在java.lang包中的最后一个类。out是对打印流类的引用,它是系统类的静态成员。println是java.io包中捆绑的打印流类的一种方法,用于打印输出。方法区、永久区、元数据区是什么关系?jvm规范中要求方法区,永久区是Hotspot虚拟机对方法区的具体实现。前者是规范,后者是实现方法。jdk1.8做了改动。说说什么是GC,为什么会有GC?GC是垃圾回收的意思。内存处理是程序员容易出问题的地方。忘记或错误的内存恢复会导致程序或系统不稳定甚至崩溃。Java虚拟机提供的GC功能可以自动监测对象是否超出范围,达到自动回收内存的目的。Java语言并没有提供明确的操作方法来释放分配的内存。Java程序员不必担心内存管理,因为垃圾收集器会自动处理它。GC中的STW是什么?Java中的Stop-The-World机制简称为STW。当执行垃圾收集算法时,Java应用程序的所有其他线程(垃圾收集除外)都被挂起。Java中的一种全局停顿现象,全局停顿,所有Java代码停止,native代码可以执行,但是不能和JVM交互。如何识别垃圾?常用的方法有两种:引用计数,很难解决对象间循环引用的问题。可达性分析算法被主流的JVM采用。下面简单说一下垃圾回收算法mark-clear算法。就像它的名字一样,该算法分为两个阶段:“标记”和“清除”。目的。复制算法,将可用内存按容量分成两个大小相等的块,一次只使用其中一个。当这块内存用完后,将存活的对象复制到另一块中,然后一次性清理掉已使用的内存空间。缺点是浪费空间,优点是回收速度快,没??有碎片。mark-compression算法,标记过程还是和“mark-clear”算法一样,只是下一步不是直接清理可回收对象,而是将所有存活的对象移到一端,完成碎片整理。分代收集算法将Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最合适的收集算法。我认为它更像是一个想法而不是算法。你知道有哪些垃圾收集器吗?串行收集器,串行收集器是最古老、最稳定、最高效的收集器,可能会产生长时间的停顿,只使用一个线程进行回收。ParNew收集器,ParNew收集器实际上是Serial收集器的多线程版本。Parallel收集器,ParallelScavenge收集器类似于ParNew收集器,Parallel收集器更注重系统的吞吐量。ParallelOld收集器,ParallelOld是老版本的ParallelScavenge收集器,采用多线程和“标记排序”算法的CMS收集器,CMS(ConcurrentMarkSweep)收集器是一种旨在获得最短恢复停顿时间的收集器.G1收集器,G1(Garbage-First)是一个面向服务器的垃圾收集器,主要针对配备多处理器和大容量内存的机器。非常大概率满足GC停顿时间要求,同时具有高吞吐量量化性能特点什么是基于堆栈和寄存器的指令集架构?前面的指令运行过程需要借助栈的数据结构来完成。主要优点是可移植性,缺点是执行速度慢。后者的寄存器指令由硬件直接提供,速度很快,但缺点是与硬件强绑定。我们主流的java虚拟机使用的是基于栈的指令集架构。什么是虚拟机堆栈?JVM规范允许每个Java线程都有自己独立的JVM栈,也就是Java方法的调用栈。调用方法时,会生成堆栈帧。方法调用返回过程其实就是栈帧的push和pop。栈帧存储在虚拟机栈中,栈帧中存储了方法的局部变量表、操作数栈、动态链接、方法的返回地址等信息。在一个线程的运行过程中,只有一个栈帧是活动的,称为“当前活动栈帧”。当前活动堆栈帧始终是虚拟机堆栈的顶部元素。为什么程序计数器是私有的?虚拟机支持多线程并发,程序计数器的私有性主要是为了线程切换后恢复正确的执行位置。在多线程的情况下,程序计数器用来记录当前线程的执行位置,这样当线程切换回来的时候,可以知道线程上次跑到哪里去了。需要注意的是,如果执行了native修饰的本地方法,程序计数器记录的是未定义地址。只有当Java代码被执行时,程序计数器才会记录下一条指令的地址。什么是安全点?比如在GC的时候,VMThread必须等到所有的Java线程都进入safepoint后才开始GC1.循环结束时(防止大循环还没进入safepoint,而其他线程正在等待它进入safepoint)2。方法返回前3.调用方法调用后4.Java对象的创建过程在抛出异常的地方清楚吗?当JVM遇到创建新对象的指令时,首先会检查这条指令的参数是否可以在常量池中定义一个类的符号引用。然后加载这个类(后面会讲到类加载过程)为对象分配内存。一种方法是“指针冲突”,一种方法是“空闲列表”,最后常用的方法是“本地线程缓冲区分配(TLAB)”,将除对象头之外的对象内存空间初始化为0,并对对象头进行必要的设置Java对象结构你了解了吗?Java对象由三部分组成:对象头、实例数据和对齐填充。对象头由两部分组成。第一部分存储对象本身的运行时数据:hashcode、GCgenerationage、lockidentificationstatus、thread持有的lock、biasedthreadID(一般为32/64位)。第二部分是指针类型,指向对象的类元数据类型(即对象代表哪个类)。如果是数组对象,对象头的另一部分用来记录数组的长度。实例数据用于存储对象真正有效的信息(包括继承自父类和自己定义的)对齐填充:JVM要求对象的起始地址必须是8字节的整数倍(8-bytealignment)Java对象定位方法你懂吗?句柄池,直接指针。方法区和永久代有什么区别?永久代也叫Perm区,只存在于HotSpotJVM中,并且只存在于JDK1.7及之前的版本中。永久代在JDK1.8中已经被完全移除,JDK1.8引入了一个新的内存区域,称为元空间。并非所有JVM都有永久代。IBM的9和Oracle的JRocket没有永久代。永久代是实现层面的东西。永久代存放的东西,基本上都是方法区指定的东西。因此,我们可以说永久代是JDK1.7中方法区的一种实现,当然HotSpotJDK1.8中的元空间也可以看作是方法区的一种实现。为什么要用元空间替换永久空间?主要有以下几点:字符串存在于永久代,容易出现性能问题和内存溢出。很难确定类和方法信息的大小,因此很难指定永久代的大小。太小容易造成永久代溢出,太大容易造成老年代溢出。永久代会给GC带来不必要的复杂度,回收效率低。去掉永久代是为了整合HotSpotJVM和JRockitVM,因为JRockit没有永久代,不需要配置永久代。文章来自小林编码
