Java工程师技术栈笔记

一、基础

1. 修饰符

1.1 几个修饰符

访问修饰符

  1. default (即缺省,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
  2. private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
  3. public : 对所有类可见。使用对象:类、接口、变量、方法
  4. protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
  5. 父类中声明为 public 的方法在子类中也必须为 public。
  6. 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
  7. 父类中声明为 private 的方法,不能够被继承。

非访问修饰符

  1. static 修饰符,用来修饰类方法和类变量。
  2. final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
  3. abstract 修饰符,用来创建抽象类和抽象方法。
  4. synchronized 和 volatile 修饰符,主要用于线程的编程。

【eg】:
在Java中 ++i、i++并不是线程安全的,要想线程安全,就用使用volatile修饰符完善的AtomicInteger

1.2 Java类加载原理与顺序

归类总结为:加载、链接、初始化
连接过程包括 验证,准备、解析三个阶段
【加载】:指的是把class字节码文件从各个来源通过类加载器装载入内存中。

【字节码来源】:一般的加载来源包括从本地路径下编译生成的.class文件,从jar包中的.class文件,从远程网络,以及动态代理实时编译
【类加载器】:一般包括启动类加载器,扩展类加载器,应用类加载器,以及用户的自定义类加载器。

【验证】:保证加载进来的字节流符合虚拟机规范,不会造成安全错误
【准备】:主要是为类变量(注意,不是实例变量)分配内存,并且赋予初值。
【解析】:将常量池内的符号引用替换为直接引用的过程。

符号引用。即一个字符串,但是这个字符串给出了一些能够唯一性识别一个方法,一个变量,一个类的相关信息,直接引用。可以理解为一个内存地址,或者一个偏移量。比如类方法,类变量的直接引用是指向方法区的指针;
而实例方法,实例变量的直接引用则是从实例的头指针开始算起到这个实例变量位置的偏移量

【初始化】:主要是对类变量初始化,是执行类构造器的过程,另说只对static修饰的变量或语句进行初始化
可以参考如下图:Java类声明周期简单分析
当初始化完成后,就可以使用了,在使用完之后,会在方法区GC的过程中对其进行卸载。至此Java的的整合生命周期也完成。参考

2集合

关于Map的算法分析

2. web容器

2.1 tomcat

2.2 jetty

3. 多线程

多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。

Java 三种创建线程的方法:
通过实现 Runnable 接口;
通过继承 Thread 类本身;
通过 Callable 和 Future 创建线程。

4. JVM

4.1 JVM介绍

JVM是Java Virtual Machine的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
Java语言的一个非常重要的特点就是与平台的无关性。而使用JVM是实现这一特点的关键。
Java语言使用jvm屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在jvm上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。
如图在这里插入图片描述
JVM在它的生存周期中有一个明确的任务,那就是运行Java程序,因此当Java程序启动的时候,就产生JVM的一个实例;当程序运行结束的时候,该实例也跟着消失了。下面我们从JVM的体系结构和它的运行过程这两个方面来对它进行比较深入的研究。

4.2 JVM内存结构

JVM都包含:堆内存、栈内存、方法区、本地方法栈、指令计数器及其他隐含寄存器

【堆内存】:所有通过new创建的对象和数组的内存都在堆中分配,堆内存中的实体不再被应用时,JVM启动垃圾回收机制,自动清除,是GC的主要区域,同样是线程共享的内存区域。堆被所有线程共享,堆区中不存放基本类型和对象引用,只存放对象本身。

其大小可以通过-Xmx和-Xms来控制

【栈内存】:栈内存保存基本数据类型、局部变量,对象的引用变量都是在栈内存中的。栈内存中的数据,没有默认初始化值,用完就消失。
【方法区】:保存方法代码(编译后的java代码)和符号表;存放要加载的类信息、静态变量、final类型的常量、属性和方法信息。类信息是由类加载器从类文件中提取出来的。

JVM用持久代(Permanet Generation)来存放方法区,可通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值。

【本地方法栈】:用于支持native方法的执行,存储了每个native方法调用的状态。

结构示意图如下:

jvm结构示意图

5.GC

5.1 GC介绍

GC是垃圾收集的意思,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显式操作方法。GC可以有效的防止内存泄露,提高可使用的内存的使用效率。
在HotSpot虚拟机中,主要有:
Minor GC:新生代GC,指发生在新生代的垃圾收集动作,所有的Minor GC都会触发全世界的暂停(stop-the-world),停止应用程序的线程,不过这个过程非常短暂。
Major GC/Full GC:老年代GC,指发生在老年代的GC。

5.2 GC算法

Java堆是被所有线程共享的一块内存区域,所有对象实例和数组都在堆上进行内存分配。为了进行高效的垃圾回收,虚拟机把堆内存划分成新生代(Young Generation)、老年代(Old Generation)和永久代(Permanent Generation)3个区域。
JVM针对新生代,主要采用复制算。针对老年代,通常采用标记-清除算法或者标记-整理算法来进行回收。

【复制算法】:新生代由 Eden 与 Survivor Space(S0,S1)构成,Survivor 幸存区是将内存分成大小相等的两块区域,每次使用其中的一块。当这一块的内存用完了,就将还存活的对象复制到另一块区域上,然后对该块进行内存回收。大小通过-Xmn参数指定,Eden 与 Survivor Space 的内存大小比例默认为8:1,可以通过-XX:SurvivorRatio 参数指定,比如新生代为10M 时,Eden分配8M,S0和S1各分配1M

【标记算法】:老年代对象存活的时间比较长、比较稳定,因此采用标记(Mark)算法来进行回收,所谓标记就是扫描出存活的对象,然后再进行回收未被标记的对象,回收后对用空出的空间要么进行合并、要么标记出来便于下次进行分配,目的就是要减少内存碎片带来的效率损耗
老年代的空间大小即-Xmx 与-Xmn 两个参数之差,用于存放经过几次Minor GC之后依旧存活的对象。当老年代的空间不足时,会触发Major GC/Full GC。

说明:事实证明,90%以上的新生代对象存活时间很短暂。使用复制算法实现简单,运行效率高,坏处是每次只能使用一半内存,内存的利用率不高;
标记整理算法,涉及两个过程,运行效率慢,且整理之后会产生不连续的内存空间

5.3 jvm调优

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值