
一、Java介绍编译型语言源代码需要通过编译器编译面向过程C面向过程面向对象C面向对象JavaGoC#解释型语言JavaScriptJava的一些特性Java是纯面向对象语言所有代码必须定义在类中不容许单独的过程与函数存在方法必须隶属于类或对象。成员通过类名静态方法或对象实例方法调用。非静态方法属于实例成员对象而静态方法才属于类成员。类的成员 类里面定义的所有东西包括静态和非静态的字段、方法、嵌套类等实例成员 必须通过对象.xxxoff-heap访问的非静态部分属于具体对象Java的组成JDKJava Delelopment Kit Java开发工具包JREJava Runtime Environment Java运行时环境JVM: Java Vertual Machine Java虚拟机二、JVM虚拟机类加载器、垃圾回收器、JIT编译器和解释器 均为JVM的组件。Java的跨平台开发javac 是 Java 编译器。它的作用是将你写的 Java 源代码.java 文件编译成字节码.class 文件JVM 可识别的格式一个Java源程序文件中定义几个类和接口则编译该文件后生成几个以.class为后缀的字节码文件。java 是解释器/运行器。负责启动 JVM 并将指定的 .class 文件加载进入JVM并执行生成可执行的二进制机器码。JVM中的内存结构线程共享直接内存直接向操作系统申请内存不受 JVM 堆内存大小限制。方法区Method Area/元空间Metaspace:是 JVM 中用来存储类的结构信息、常量、静态变量、JIT 编译代码等的内存区域。运行时常量池JVM常量池属于方法区的一部分存放编译期生成的各种字面量和符号引用。可以动态添加常量如 String.intern()。Java 堆(Heap)是垃圾收集器管理的主要区域因此也被称作GC 堆Garbage Collected Heap。是 JVM 中最大的一块内存区域,存储着所有通过 new 关键字创建的对象实例和数组以及这些对象的实例变量字段等。是垃圾回收器GC主要管理的区域。如果没有内存可用且 GC 无法回收会抛出 OutOfMemoryError。线程私有(独立拥有)程序计数器当前线程所执行字节码的行号指示器。本地方法栈:执行 native 本地方法,运行 C/C 等 native 代码如 JNI虚拟机栈JVM Stack栈区是 JVM 为每个线程分配的运行内存区域存储每个方法调用时的栈帧栈帧是栈区的最小单位。栈帧方法调用时在栈区里开辟的一小块内存单元存储方法执行过程中所需要的信息局部变量-存储了基本数据类型的值、对象的引用变量、操作数、中间结果和方法出口等。压栈出栈方法调用 → 入栈方法结束 → 出栈。异常情况StackOverflowError栈深度过大。OutOfMemoryError无法申请足够内存创建新的栈。3、池Pool其实是一个非常重要的性能优化思想Java 大量使用“池”贯穿了JVM 底层、标准库、开发框架与应用开发各个层次。是“资源复用”机制避免频繁创建与销毁相同类型的对象或资源降低性能开销与内存浪费。层次池的名称位置说明外存层面Class 文件常量池Constant Pool Table存储在磁盘上的 .class 文件内部属于 Class 文件格式规范同时为JVM 加载和执行类文件提供必要的符号信息支持。JVM内存层面运行时常量池方法区元空间运行时常量池是Class 文件常量池被JVM加载在内存中的映射字符串常量池堆JDK1.7字面量字符串共享包装类对象缓存池堆Integer、Byte、Boolean 缓存标准库层面线程池ThreadPoolExecutor堆复用线程资源对象池Object Pool堆Apache Commons Pool 等NIO ByteBuffer 池堆/堆外复用缓冲区Netty应用层面数据库连接池堆DBCP、HikariCP、Druid 等缓存池对象缓存堆业务自定义缓存池4、JVM 的垃圾回收机制GC garbage collectionMinor GC主要回收的是年轻代Young Generation的内存。年轻代主要包括Eden 区和两个Survivor 区S0 和 S1。Full GCFull GC 会回收整个堆内存包括年轻代和老年代Old Generation当JVM发现某些对象不再被引用时,就会将其标记并在合适的时机进行回收,这个过程是动态的、持续的。GC不仅管理堆内存还涉及方法区元空间。Java 中的垃圾回收算法有四种分别是标记清除法、标记整理法、复制算法、分代收集算法堆内存采用分代结构分为新生代和老年代。JDK 8 版本之后方法区HotSpot 的永久代被彻底移除了JDK1.7 就已经开始了取而代之是元空间元空间使用的是直接内存。新创建的对象总是在新生代的Eden区进行分配Java GC是可以手动触发的比如通过System.gc()方法尽管这只是建议JVM进行垃圾回收但并不保证一定会执行。JVM可以自主决定何时触发GC。大部分情况对象都会首先在 Eden 区域分配。当 eden 区没有足够空间进行分配时虚拟机将发起一次 Minor GC。经过第一次 Minor GC 后仍然能够存活并且能被 Survivor 容纳的话将被移动到 Survivor 空间中并将对象年龄设为 1.对象在 Survivor 中每熬过一次 MinorGC,年龄就增加 1 岁当它的年龄增加到一定程度默认为 15 岁就会被晋升到老年代中。在Minor GCYGC时若存活对象无法全部放入To Survivor区超出的部分会直接晋升到老年代。对象晋升到老年代的年龄阈值可以通过参数 -XX:MaxTenuringThreshold 来设置。当老年代无法容纳新晋升的对象时会触发 Full GC仅限一些垃圾回收器比如Serial / Parallel Scavenge。JAVA进程的JVM参数配置如下-Xms1G -Xmx2G -Xmn500M -XX:MaxPermSize64M -XX:UseConcMarkSweepGC -XX:SurvivorRatio3,-Xms1G → 初始堆大小 1GB-Xmx2G → 最大堆大小 2GB-Xmn500M → 新生代大小 500MB-XX:MaxPermSize64M → 永久代最大值 64MB仅适用于 JDK 8 之前-XX:SurvivorRatioN → Eden : Survivor N : 1 : 1即 Eden 占新生代的 3/5两个 Survivor 区各占 1/5垃圾回收算法1.1.标记-清除算法该算法分为“标记”和“清除”阶段首先标记出所有不需要回收的对象在标记完成后统一回收掉所有没有被标记的对象。它是最基础的收集算法后续的算法都是对其不足进行改进得到的。特点1. 效率不行标记和清除的效率都不高2. 标记和清除后会产生大量的不连续的空间分片可能会导致之后程序运行的时候需分配大对象而找不到连续分片而不得不触发一次GC1.2. 复制算法为了解决效率问题“复制”收集算法出现了。它可以将内存分为大小相同的两块每次使用其中的一块。当这一块的内存使用完后就将还存活的对象复制到另一块去然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。特点1. 不会产生空间碎片2. 内存使用率极低1.3. 标记-整理算法根据老年代的特点提出的一种标记算法标记过程仍然与“标记-清除”算法一样但后续步骤不是直接对可回收对象回收而是让所有存活的对象向一端移动然后直接清理掉端边界以外的内存。特点1. 适用于存活对象多垃圾少的情况2. 需要整理的过程无空间碎片产生1.4.分代收集算法当前虚拟机的垃圾收集都采用分代收集算法这种算法没有什么新的思想只是根据对象存活周期的不同将内存分为几块。一般将 java 堆分为新生代和老年代这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。比如在新生代中每次收集都会有大量对象死去所以可以选择复制算法只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的而且没有额外的空间对它进行分配担保所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。为了提高GC效率所以 HotSpot 要分为新生代和老年代。三、Kotlin介绍几乎可以说 Kotlin 是在Java 的地基上盖的新房子。Kotlin 是一种现代化的、与 Java 100% 互操作的 JVM 语言它可以直接使用 Java 的所有资源但在语法、空指针安全和开发体验上更先进。1.运行平台相同Java 程序编译成字节码.class 文件运行在JVMJava Virtual Machine上。Kotlin 也是编译成字节码运行在同一个 JVM 上。所以 Kotlin 和 Java 的 .class 文件可以在同一个项目中无缝混用。2.语法兼容Kotlin 可以直接调用 Java 的类、方法、库没有任何额外转换。Java 也能调用 Kotlin 写的代码虽然 Kotlin 的一些特性在 Java 调用时可能不那么优雅。Kotlin 中声明变量不必指定变量的类型Kotlin 会隐式指定类型。Kotlin 中声明变量可以使用 var 或 val 关键字Kotlin 中val 变量赋值后无法更改使用 val 关键字声明的变量Kotlin 中的 println() 函数调用了 System.out.println() 函数3.语言设计目标Kotlin 由JetBrainsIntelliJ IDEA 的公司开发设计目标是更简洁减少 Java 的模板代码更安全尤其是空指针安全更现代支持协程、扩展函数、数据类等特性