Java总结

Java虚拟机:

Class Loader:依据特定格式,加载class文件到内存;

Execution Engine:对命令进行解析;

Native Interface:融合不同开发语言的原生库为Java所用;

Runtime Data Area:JVM内存空间的结构模型;

Java反射:

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;

对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

类从编译到到执行的过程:

1.编译器将name.java源文件编译为name.class字节码文件;

2.ClassLoader将字节码转换为JVM中的Class<name>对象;

3.JVM利用Class<name>对象实例化为name对象;

ClassLoader:

ClassLoader 在Java中有着非常重要的作用,它主要工作在Class装载的加载阶段,其主要作用是从系统外部获得Class二进制数据流。

它是Java的核心组件,所有的Class都有ClassLoader进行加载,ClassLoader 负责通过将Class文件里的二进制数据流装载进系统,然后

交给Java虚拟机进行连接,初始化等操作。

 类加载器的双亲委派机制:

.......

避免多份同样字节码的加载;

LoadClass 和forName的区别;

类的装载过程:

JVM内存模型:

线程私有:

  1.程序计数器

    当前线程所执行的字节码行号指示器(逻辑)

    改变计数器的值来选取下一条需要执行的字节码指令

    和线程是一对一的关系即“线程私有”

    对Java方法计数,如果是Native方法则计数器值为Undefined

    不会发生内存泄露

  2.虚拟机栈

    Java方法执行的内存模型

    包含多个栈帧

    (局部变量表:包含方法执行过程中的所有变了;操作栈:入栈,出栈,复制,交换,产生消费变量;动态链接,返回地址)

    递归引发java.lang.StackOverflowError异常:递归过深,栈帧超出虚拟栈深度;

  3.本地方法栈

    与虚拟机栈相似,主要作用于标注了native的方法;

所有线程共享:

1.MetaSpace(类加载信息OOM)

2.堆(数组和类对象OOM)常量池(字面量和符号引用量OOM)

MetaSpace相比PermGen的优势:

1.字符串常量池存在永久代中,容易出现性能问题和内存溢出;

类和方法的信息大小难以确定,给永久代大大小指定带来困难;

永久代会为GC带来不必要的复杂性;

方便HotSpot与其他JVM如Jrockit的集成;

Java 堆(Heap):

  对象实例的分配区域

  GC管理的主要区域

JVM三大性能调优参数-Xms -Xmx -Xss

java -Xms 128m -Xmx 128m -Xss 256k -jar xxxx.jar

-Xss:规定了每个线程虚拟机栈(堆栈)的大小

-Xms:堆初始值

-Xmx:堆能达到的最大值

Java内存模型中堆和栈的区别-内存分配策略

静态存储:编译时确定每个暑假目标在运行是的存储空间需求;

栈式存储:数据区需求在编译时未知,运行时模块入口前确定;

堆式存储:编译时或运行时模块入口都无法确定,动态分配;

Java内存模型中堆和栈的区别-联系

联系:引用对象,数组时,栈里定义变量保存堆中目标的首地址;

管理方式:栈自动释放,堆需要GC;

空间大小:栈比堆小;

碎片:栈产生的碎片远小于堆;

分配方式:栈支持静态和动态分配,而堆仅支持动态分配;

效率:栈的效率比堆高;

元空间,堆,线程独占部分的联系-内存角度

元空间:类信息

Java堆:类对象

线程独占:变量引用,参数引用,本地变量

引用计数法:

通过判断对象的引用数量来决定对象是否可以回收;

每个对象实例都有一个引用计数器,被引用则+1,完成引用则-1;

任何引用计数为0的对象实例可以被当做垃圾回收;

优点:执行效率高,程序执行受影响较小;

缺点:无法检测出循环引用的情况,导致内存泄露;

可达性分析算法:

通过判断对象的引用链是否可达来决定对象是否可以被回收;

可作为GC Root的对象:

虚拟机栈中引用的对象(栈帧中的本地变量表)

方法区中的常量引用的对象;

方法区中的类静态属性引用的对象;

本地方法栈中JNI(Native方法)的引用对象;

活跃线程的引用对象;

垃圾回收算法:

标记清除算法(Mark and Sweep)

标记:从根集合进行扫描,对存活的对象进行标记;

清除:对堆内存从头到尾进行线性遍历,回收不可达对象内存;

--

存在碎片化问题;

复制算法(Copying)

分为对象面和空闲面;

对象在对象面上创建;

存活的对象呗从对象面复制到空闲面;

将对象面所有对象内存清除;

--

解决了碎片化问题;

顺序分配内存,简单高效;

适用于对象存活率低的场景;

标记整理算法(Compacting)

标记:从根节点进行扫描,对存活的对象进行标记;

清除:移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收;

--

避免了内存的不连续行;

不用设置两块内存互换;

适用于存活率高的场景;

分代收集算法(Generational Collector)

1.垃圾回收算法的组合

2.按照对象生命周期的不同划分区域以采用不同的来及回收算法;

年轻带:尽可能快速低收集掉那些生命周期短的对象;1/3堆空间

Eden区 8/10

两个Survivor区1/10,1/10

老年代:2/3堆空间

Full GC和Major GC

Full GC比Minor GC慢,但执行频率低;

常用调优参数

-XX:SurvivorRatio:Eden和Survivor的比值,默认8:1

-XX:NewRatio:老年代和年轻带内存大小的比例

-XX:MaxTenuringThreshold:对象从年轻带晋升到老生带经过GC次数的最大阈值;

GC分类

Minor GC

Full GC

触发Full GC的条件:

老年代空间不足;

永久代空间不足;

CMS GC时出现promotion failed,concurrent mode failuer

Minor GC晋升到老年代的平均大小大于老年代的剩余空间;

调用System.gc()

使用RMI来进行RPC或管理的JDK应用,每小时执行1次Full GC;

Stop-the-World:

JVM由于要执行GC而停止了应用程序的执行;

任何一种GC算法都会发生;

多数GC优化通过减少Stop-the-World发生的时间来提高程序性能;

Safepoint:

分析过程中,对象引用关系不会发生变化的点;

产生Safepoint的地方:方法调用;循环跳转;异常跳转等;

安全点数量得适中;

JVM运行模式:检查方法,java -version

server

clinet

 年轻代垃圾收集器:

Serial收集器(-XX:+UseSerialGC,复制算法)

单线程收集,进行垃圾收集时,必须暂停所有工作线程;

简单高效,Client模式下默认的年轻代收集器;

ParNew收集器(-XX:UseParNewGC,复制算法)

多线程收集,其余的行为,特点跟Serial收集器一样;

单核执行效率不如Serial,在多核下执行才有优势;

Paralel Scavenge收集器(-XX:+UseParallel GC,复制算法)

比起关注用户线程停顿时间,更关注系统的吞吐量;

在多核下执行才有优势,Server模式下默认的年轻代收集器;

----------------------------------------------------------------------------------

老年代垃圾收集器

Serial Old收集器(-XX:+UseSerialOldGC,标记-整理算法)

单线程收集,运行垃圾收集时,必须暂停所有工作线程;

简单高效,Client模式下默认的老年代收集器;

Parallel Old收集器(-XX:+UseParallelOld GC,标记-整理算法)

多线程,吞吐量优化;

CMS收集器(-XX:UseConcMarkSweepGC,标记-清除算法)

初始标记:stop-the-world

并发标记:并发追溯标记,程序不会停顿;

并发预清理:查找执行并发标记阶段从年轻代晋升到老年代的对象;

重新标记:暂停虚拟机,扫描CMS堆中的剩余对象;

并发清理:清理垃圾对象,程序不会停顿;

并发重置:重置CMS收集器的数据结构;

G1收集器(-XX:UseG1GC,复制+标记-整理算法)

Garbage First收集器的特点:

并行和并发

分代收集

空间整合

可预测的停顿

将整个Java堆内存划分成多个大小相等的Region;

年轻代和老年代不再物理隔离;

Object的finalize()的方法的作用

......

Java中的强引用,软引用,弱引用,虚引用的作用:

强引用(Strong Reference)

软引用(Soft Reference)

弱引用(Weak Reference)

虚引用(Phantom Reference)

进程是资源分配的最小单位,线程是CPU调度的最小单位;

所有与进程相关的资源,都被记录在PCB中;

进程是抢占处理机的调度单位;线程属于某个进程,共享其资源;

线程只由堆栈寄存器,程序计数器和TCB组成;

总结:

线程不能看做独立应用,而进程可看做独立应用;

进程有独立的地址空间,相互不影响,线程只是进程的不同执行路径;

线程没有独立的地址空间,多进程的程序比多线程程序健壮;

进程的切换比线程的切换开销大;

Java对操作系统提供的功能进行封装,包括进程和线程:

运行一个程序产生一个进程,进程包含至少一个线程;

每个进程对应一个JVM实例,多个线程共享JVM里面的堆;

Java采用单线程编程模型,程序会自动创建主线程;

主线程可以创建子线程原则上要后与子线程完成执行;

Thread中的start和run方法的区别:

调用start()方法会创建一个新的子线程并启动;

run()方法只是Thread的一个普通方法的调用;

Thread和Runnable的关系:

Thread是实现了Runnable接口的类,使得run支持多线程;

因类的单一继承原则,推荐多使用Runnabe接口;

 如何给run()方法传参

实现的方法主要有三种

构造函数传参

成员变量传参

回调函数传参

如何实现处理线程的返回值?

实现的方式主要有三种

1.主线程等待法

2.使用Thread类的join()阻塞当前线程以等待子线程处理完毕;

3.通过Callable接口实现:通过FutureTask Or线程池获取;

线程的六个状态:

1.新建(New):创建后尚未启动的线程的状态;

2.运行(Runnable):包含Running和Ready;

3.无限期等待(Waiting):不会被分配CPU执行时间,需要显示被唤醒;

4.限期等待(Timed Waiting):在一定时间后会由系统自动唤醒;

5.阻塞(Blocked):等待获取排它锁;

6.结束(Terminated):已终止线程的状态,线程已经结束执行;

Sleep 和Wait的区别:

基本的差别:

1.sleep是Thread类的方法,wait是Object类中定义的方法;

2.sleep()方法可以在任何地方使用;

3.wait()方法只能在synchronized方法或synchronized块中使用;

最主要的本质区别:

Thread.sleep只会让出CPU,不会导致锁行为的改变;

Object.wait不仅让出CPU,还会释放已经占有的同步资源锁;

notify和notifyAll 的区别:

...

yield:

...

如何中断线程:

...

synchronized

synchronized和ReentrantLock的区别:

...

Java内存模型JMM:

JMM的中内存和工作内存:

JMM如何解决可见性问题:

volatile

volatile和synchronized的区别;

Java线程池

原文地址:https://www.cnblogs.com/songyuejie/p/12594218.html