高端网站设计新鸿儒,民宿行业网站建设方案,源码买卖网站,外贸网站用什么空间1、虚拟机的自动内存管理和C/C的区别
C/C开发程序时需要为每一个new操作去写对应的delete/free操作#xff0c;不容易出现内存泄漏和溢出问题。而Java程序将内存控制权交给了Java虚拟机
2、JVM的运行机制
1、Java程序的具体运行过程如下#xff1a;
Java源文件被编译器编…1、虚拟机的自动内存管理和C/C的区别
C/C开发程序时需要为每一个new操作去写对应的delete/free操作不容易出现内存泄漏和溢出问题。而Java程序将内存控制权交给了Java虚拟机
2、JVM的运行机制
1、Java程序的具体运行过程如下
Java源文件被编译器编译成字节码文件JVM将字节码文件编译成相应操作系统的机器码机器码调用相应操作系统的本地方法库执行相应的方法
2、虚拟机结构
Java虚拟机包括类加载器子系统、运行时数据区、执行引擎、本地接口库等
3、JVM的内存区域
1、内存区域划分 线程私有区域、线程共享区域和直接内存
线程私有区域的生命周期与线程相同线程共享区域的生命周期与虚拟机相同直接内存也叫堆外内存它不是JVM运行时数据区的一部分但在并发编程中被频繁调用
2、程序计数器 线程私有无内存溢出问题
每个运行中的线程都有一个独立的程序计数器在方法正在执行时该方法的程序计数器记录的是实时虚拟机字节码指令的地址如果该方法执行的是Native方法则程序计数器的值为空程序计数器属于“线程私有”的内存区域它是唯一没有Out Of Memory内存溢出的区域
3、虚拟机栈 线程私有描述Java方法的执行过程
虚拟机栈是描述Java方法的执行过程的内存模型它在当前栈帧中存储了局部变量表、操作数栈、动态链接、方法出口等信息。栈帧用来记录方法的执行过程在方法被执行时虚拟机会为其创建一个与之对应的栈帧方法的执行和返回对应栈帧在虚拟机栈中的入栈和出栈
4、本地方法区 线程私有
本地方法区和虚拟机栈的作用类似区别是虚拟机栈为执行Java方法服务本地方法栈为Native方法服务
5、堆 也叫作运行时内存线程共享
在JVM运行过程中创建的对象和产生的数据都被存储在堆中堆是被线程共享的内存区域也是垃圾收集器进行垃圾回收的最主要的内存区域由于现代JVM采用分代收集算法因此Java堆从GCGarbage Collection垃圾回收的角度还可以细分为新生代、老年代和永久代
6、方法区 线程共享
方法区也被称为永久代用于存储常量、静态变量、类信息、即时编译器编译后的机器码、运行时常量池等数据永久代的内存回收主要针对常量池的回收和类的卸载因此可回收的对象很少在即时编译后代码的内容将在执行阶段类加载完成后被保存在方法区的运行时常量池中
4、JVM的运行时内存
1、JVM的运行时内存也叫作JVM堆可分类为如下图所示 2、新生代 Eden区、ServivorTo区和ServivorFrom区
JVM新创建的对象除了大对象外会被存放在新生代默认占1/3堆内存空间。由于JVM会频繁创建对象所以新生代会频繁触发MinorGC进行垃圾回收Eden区Java新创建的对象首先会被存放在Eden区如果新创建的对象属于大对象则直接将其分配到老年代ServivorTo区保留上一次MinorGC时的幸存者ServivorFrom区将上一次MinorGC时的幸存者作为这一次MinorGC的被扫描者新生代的GC过程叫作MinorGC采用复制算法实现
3、老年代
老年代主要存放有长生命周期的对象和大对象。老年代的GC过程叫作MajorGC采用标记清除算法在老年代对象比较稳定MajorGC不会被频繁触发。在进行MajorGC前JVM会进行一次MinorGC在MinorGC过后仍然出现老年代空间不足或无法找到足够大的连续空间分配给新创建的大对象时会触发MajorGC进行垃圾回收释放JVM的内存空间
4、永久代
永久代指内存的永久保存区域主要存放Class和Meta元数据的信息。Class在类加载时被放入永久代。永久代和老年代、新生代不同GC不会在程序运行期间对永久代的内存进行清理这也导致了永久代的内存会随着加载的Class文件的增加而增加在加载的Class文件过多时会抛出Out Of Memory异常需要注意的是在Java 8中永久代已经被元数据区也叫作元空间取代。元数据区的作用和永久代类似二者最大的区别在于元数据区并没有使用虚拟机的内存而是直接使用操作系统的本地内存。因此元空间的大小不受JVM内存的限制只和操作系统的内存有关。
5、确定垃圾
1、如何确定垃圾 Java采用引用计数法和可达性分析来确定对象是否应该被回收 2、引用计数法
在Java中如果要操作对象就必须先获取该对象的引用因此可以通过引用计数法来判断一个对象是否可以被回收。在为对象添加一个引用时引用计数加1在为对象删除一个引用时引进计数减1如果一个对象的引用计数为0则表示此刻该对象没有被引用可以被回收引用计数法容易产生循环引用问题。循环引用指两个对象相互引用导致它们的引用一直存在而不能被回收
3、可达性分析
具体做法是首先定义一些GC Roots对象然后以这些GC Roots对象作为起点向下搜索如果在GC roots和一个对象之间没有可达路径则称该对象是不可达的不可达对象要经过至少两次标记才能判定其是否可以被回收如果在两次标记后该对象仍然是不可达的则将被垃圾收集器回收。
6、垃圾回收算法
4种算法标记清除、复制、标记整理、分代收集
1、标记清除算法
标记清除算法是基础的垃圾回收算法其过程分为标记和清除两个阶段。在标记阶段标记所有需要回收的对象在清除阶段清除可回收的对象并释放其所占用的内存空间由于标记清除算法在清理对象所占用的内存空间后并没有重新整理可用的内存空间因此如果内存中可被回收的小对象居多则会引起内存碎片化的问题继而引起大对象无法获得连续可用空间的问题
2、复制算法
复制算法是为了解决标记清除算法内存碎片化的问题而设计的。复制算法首先将内存划分为两块大小相等的内存区域即区域1和区域2新生成的对象都被存放在区域1中在区域1内的对象存储满后会对区域1进行一次标记并将标记后仍然存活的对象全部复制到区域2中这时区域1将不存在任何存活的对象直接清理整个区域1的内存即可复制算法的内存清理效率高且易于实现但由于同一时刻只有一个内存区域可用即可用的内存空间被压缩到原来的一半因此存在大量的内存浪费
3、标记整理算法
标记整理算法结合了标记清除算法和复制算法的优点其标记阶段和标记清除算法的标记阶段相同在标记完成后将存活的对象移到内存的另一端然后清除该端的对象并释放内存
4、分代收集算法
无论是标记清除算法、复制算法还是标记整理算法都无法对所有类型长生命周期、短生命周期、大对象、小对象的对象都进行垃圾回收。因此针对不同的对象类型JVM采用了不同的垃圾回收算法该算法被称为分代收集算法分代收集算法根据对象的不同类型将内存划分为不同的区域JVM将堆划分为新生代和老年代。新生代主要存放新生成的对象其特点是对象数量多但是生命周期短在每次进行垃圾回收时都有大量的对象被回收老年代主要存放大对象和生命周期长的对象因此可回收的对象相对较少。因此JVM根据不同的区域对象的特点选择了不同的算法大部分JVM在新生代都采用了复制算法JVM将新生代进一步划分为一块较大的Eden区和两块较小的Servivor区Servivor区又分为ServivorFrom区和ServivorTo区。JVM在运行过程中主要使用Eden区和ServivorFrom区进行垃圾回收时会将在Eden区和ServivorFrom区中存活的对象复制到ServivorTo区然后清理Eden区和ServivorFrom区的内存空间老年代主要存放生命周期较长的对象和大对象因而每次只有少量非存活的对象被回收因而在老年代采用标记清除算法在JVM中还有一个区域即方法区的永久代永久代用来存储Class类、常量、方法描述等。在永久代主要回收废弃的常量和无用的类JVM内存中的对象主要被分配到新生代的Eden区和ServivorFrom区在少数情况下会被直接分配到老年代。在新生代的Eden区和ServivorFrom区的内存空间不足时会触发一次GC该过程被称为MinorGC。 在MinorGC后在Eden区和ServivorFrom区中存活的对象会被复制到ServivorTo区然后Eden区和ServivorFrom区被清理。如果此时在ServivorTo区无法找到连续的内存空间存储某个对象则将这个对象直接存储到老年代。若Servivor区的对象经过一次GC后仍然存活则其年龄加1。在默认情况下对象在年龄达到15时将被移到老年代
7、Java中的4中引用类型
强引用在Java中最常见的就是强引用。在把一个对象赋给一个引用变量时这个引用变量就是一个强引用有强引用的对象一定为可达性状态所以不会被垃圾回收机制回收。因此强引用是造成Java内存泄漏Memory Link的主要原因。软引用软引用通过SoftReference类实现。如果一个对象只有软引用则在系统内存空间不足时该对象将被回收弱引用弱引用通过WeakReference类实现如果一个对象只有弱引用则在垃圾回收过程中一定会被回收虚引用虚引用通过PhantomReference类实现虚引用和引用队列联合使用主要用于跟踪对象的垃圾回收状态
8、分代收集算法和分区收集算法
分代收集算法JVM根据对象存活周期的不同将内存划分为新生代、老年代和永久代并根据各年代的特点分别采用不同的GC算法分区收集算法分区算法将整个堆空间划分为连续的大小不同的小区域对每个小区域都单独进行内存使用和垃圾回收这样做的好处是可以根据每个小区域内存的大小灵活使用和释放内存分区收集算法可以根据系统可接受的停顿时间每次都快速回收若干个小区域的内存以缩短垃圾回收时系统停顿的时间最后以多次并行累加的方式逐步完成整个内存区域的垃圾回收
9、垃圾收集器
JVM针对新生代和老年代分别提供了多种不同的垃圾收集器针对新生代提供的垃圾收集器有Serial、ParNew、Parallel Scavenge针对老年代提供的垃圾收集器有Serial Old、Parallel Old、CMS还有针对不同区域的G1分区收集算法
1、Serial垃圾收集器 单线程复制算法
Serial垃圾收集器基于复制算法实现它是一个单线程收集器在它正在进行垃圾收集时必须暂停其他所有工作线程直到垃圾收集结束对于单CPU运行环境来说没有线程交互开销可以获得最高的单线程垃圾收集效率因此Serial垃圾收集器是Java虚拟机运行在Client模式下的新生代的默认垃圾收集器。
2、ParNew垃圾收集器 多线程复制算法
ParNew垃圾收集器是Serial垃圾收集器的多线程实现同样采用了复制算法它采用多线程模式工作除此之外和Serial收集器几乎一样ParNew垃圾收集器在垃圾收集过程中会暂停所有其他工作线程是Java虚拟机运行在Server模式下的新生代的默认垃圾收集器。
3、Parallel Scavenge垃圾收集器 多线程复制算法
Parallel Scavenge收集器是为提高新生代垃圾收集效率而设计的垃圾收集器基于多线程复制算法实现在系统吞吐量上有很大的优化可以更高效地利用CPU尽快完成垃圾回收任务
4、Serial Old垃圾收集器 单线程标记整理算法
Serial Old垃圾收集器是Serial垃圾收集器的老年代实现同Serial一样采用单线程执行不同的是Serial Old针对老年代长生命周期的特点基于标记整理算法实现Serial Old垃圾收集器是JVM运行在Client模式下的老年代的默认垃圾收集器。
5、Parallel Old垃圾收集器 多线程标记整理算法
Parallel Old垃圾收集器采用多线程并发进行垃圾回收它根据老年代长生命周期的特点基于多线程的标记整理算法实现
6、CMS垃圾收集器
CMSConcurrent Mark Sweep垃圾收集器是为老年代设计的垃圾收集器其主要目的是达到最短的垃圾回收停顿时间基于线程的标记清除算法实现以便在多线程并发环境下以最短的垃圾收集停顿时间提高系统的稳定性
7、G1垃圾收集器
G1Garbage First垃圾收集器为了避免全区域垃圾收集引起的系统停顿将堆内存划分为大小固定的几个独立区域独立使用这些区域的内存资源并且跟踪这些区域的垃圾收集进度同时在后台维护一个优先级列表在垃圾回收过程中根据系统允许的最长垃圾收集时间优先回收垃圾最多的区域相对于CMS收集器G1垃圾收集器两个突出的改进基于标记整理算法不产生内存碎片可以精确地控制停顿时间在不牺牲吞吐量的前提下实现短停顿垃圾回收
10、网络编程模型
1、阻塞I/O模型
阻塞I/O模型的工作流程为在用户线程发出I/O请求之后内核会检查数据是否就绪此时用户线程一直阻塞等待内存数据就绪在内存数据就绪后内核将数据复制到用户线程中并返回I/O执行结果到用户线程此时用户线程将解除阻塞状态并开始处理数据典型的阻塞I/O模型的例子为data socket.read()如果内核数据没有就绪Socket线程就会一直阻塞在read()中等待内核数据就绪
2、非阻塞I/O模型
非阻塞I/O模型指用户线程在发起一个I/O操作后无须阻塞便可以马上得到内核返回的一个结果如果内核返回的结果为false则表示内核数据还没准备好需要稍后再发起I/O操作。一旦内核中的数据准备好了并且再次收到用户线程的请求内核就会立刻将数据复制到用户线程中并将复制的结果通知用户线程
3、多路复用I/O模型
在多路复用I/O模型中会有一个被称为Selector的线程不断轮询多个Socket的状态只有在Socket有读写事件时才会通知用户线程进行I/O读写操作。多路复用I/O模型是多线程并发编程用得较多的模型Java NIO就是基于多路复用I/O模型实现的在实际应用中在多路复用方法体内一般不建议做复杂逻辑运算只做数据的接收和转发将具体的业务操作转发给后面的业务线程处理
4、信号驱动I/O模型
在信号驱动I/O模型中在用户线程发起一个I/O请求操作时系统会为该请求对应的Socket注册一个信号函数然后用户线程可以继续执行其他业务逻辑在内核数据就绪时系统会发送一个信号到用户线程用户线程在接收到该信号后会在信号函数中调用对应的I/O读写操作完成实际的I/O请求操作
5、异步I/O模型
在异步I/O模型中用户线程会发起一个asynchronous read操作到内核内核在接收到synchronous read请求后会立刻返回一个状态来说明请求是否成功发起在此过程中用户线程不会发生任何阻塞接着内核会等待数据准备完成并将数据复制到用户线程中在数据复制完成后内核会发送一个信号到用户线程通知用户线程asynchronous读操作已完成
6、Java NIO
Java NIO的实现主要涉及三大核心内容Selector选择器、Channel通道和Buffer缓冲区传统I/O基于数据流进行I/O读写操作而Java NIO基于Channel和Buffer进行I/O读写操作并且数据总是被从Channel读取到Buffer中或者从Buffer写入Channel中Channel和I/O中的Stream流类似只不过Stream是单向的而Channel是双向的既可以用来进行读操作也可以用来进行写操作。Buffer实际上是一个容器其内部通过一个连续的字节数组存储I/O上的数据Selector用于检测在多个注册的Channel上是否有I/O事件发生并对检测到的I/O事件进行相应的响应和处理
11、JVM的类加载机制
1、JVM的类加载阶段 加载、验证、准备、解析、初始化。
加载类加载过程主要包含将Class文件读取到运行时区域的方法区内在堆中创建java.lang.Class对象并封装类在方法区的数据结构的过程验证主要用于确保Class文件符合当前虚拟机的要求保障虚拟机自身的安全只有通过验证的Class文件才能被JVM加载准备主要工作是在方法区中为类变量分配内存空间并设置类中变量的初始值解析JVM会将常量池中的符号引用替换为直接引用初始化主要通过执行类构造器的方法为类进行初始化。方法是在编译阶段由编译器自动收集类中静态语句块和变量的赋值操作组成的。JVM规定只有在父类的方法都执行成功后子类中的方法才可以被执行在一个类中既没有静态变量赋值操作也没有静态语句块时编译器不会为该类生成方法
2、类加载器 启动类加载器、扩展类加载器和应用程序类加载器
启动类加载器负责加载Java_HOME/lib目录中的类库或通过-Xbootclasspath参数指定路径中被虚拟机认可的类库扩展类加载器负责加载Java_HOME/lib/ext目录中的类库或通过java.ext.dirs系统变量加载指定路径中的类库应用程序类加载器负责加载用户路径classpath上的类库
3、双亲委派机制
JVM通过双亲委派机制对类进行加载。双亲委派机制指一个类在收到类加载请求后不会尝试自己加载这个类而是把该类加载请求向上委派给其父类去完成其父类在接收到该类加载请求后又会将其委派给自己的父类以此类推这样所有的类加载请求都被向上委派到启动类加载器中
4、OSGI
OSGIOpen Service Gateway Initiative是Java动态化模块化系统的一系列规范旨在为实现Java程序的模块化编程提供基础条件基于OSGI的程序可以实现模块级的热插拔功能在程序升级更新时可以只针对需要更新的程序进行停用和重新安装极大提高了系统升级的安全性和便捷性
参考
书籍《Offer来了》