做招聘网站怎么运作,盱眙县建设局网站,wordpress安装空白页,友链堆分配参数#xff1a; -XX:PrintGC 使用该参数#xff0c;虚拟机启动后#xff0c;只要遇到GC就会打印日志#xff1b; -XX#xff1a;UseSerialGC 配置串行回收器#xff1b; -XX#xff1a;PrintGCDeltails 可以查看详细信息#xff0c;包括各个区的情况 -Xms#… 堆分配参数 -XX:PrintGC 使用该参数虚拟机启动后只要遇到GC就会打印日志 -XXUseSerialGC 配置串行回收器 -XXPrintGCDeltails 可以查看详细信息包括各个区的情况 -Xms设置Java程序启动时初始堆的大小主要参数 -Xmx设置Java程序能获得的最大堆大小主要参数 新生代的配置 -Xmn: 可以设置新生代的大小设置一个比较大的新生代会减少老年代的大小这个设置对系统性能以及GC行为有很大的影响新生代大小一般会设置整个堆空间的1/3到1/4左右。 备注在实际工作中可以直接将初始的堆大小与最大堆大小设置相等这样的好处是可以减少程序运行时的垃圾回收次数从而提高性能。 常见异常 java.lang.OutOfMemoryError.Java heap spacess---heap JVM中如果98%的时间是用于GC且可用的Heap size不足2%的时候将抛出此异常信息。 -Xms -Xmx java.lang.OutOfMemoryError.PermGen space ---no heap -XX:PermSize -XX:MaxPermSize StrackOverflowError Java虚拟机在运行时调用方法时都需要创建栈帧当栈的空间不够时就会产生StrackOverflowError -Xss JVM中的参数 以-X开头的都是非标准的这些参数并不保证在所有的JVM上都被实现。 -Xmx -Xmn -Xms 以-XX开头的都是不稳定的并且不推荐在生产环境中使用这些参数的改动也不会发布通知。 -XXPermsize -XXMaxPermsize JVM选项的说明 布尔型参数选项-XX表示打开-XX-表示关闭。-XX.PrintGCDetails 数字型参数选项通过-XX设定。 字符型参数选项通过-XX设定通常用来指定一个文件、路径或者一个命令列表 -Xms初始堆大小 -Xmx最大堆大小 -XXNewSizen 设置年轻代的大小 -XXNewRation 设置年轻代和老年代的比值。如3则表示年轻代和老年代的比值为1:3 -XXSurvivorRation 年轻代中Eden与两个Survivor区的比值。如为3则表示EdenSurvivor3:2。一个Survivor占整个年轻代的1/5. -XXMaxPermSizen 设置永久代的大小 JVM GC 串行回收器Serial Collector 并行回收器Parallel Collector 并行合并回收器Parallel Compacting Collection 并发标记清除回收器Concurrent Mark-Sweep Collector应用广泛 G1垃圾收集器Jdk7未来的主流 并行算法是用多线程进行垃圾回收回收期间会暂停程序的执行而并发算法也是多线程回收但期间不停止应用执行。所以并发算法适用于交互性高的一些程序。经过观察并发算法会减少年轻代的大小其实就是使用了一个大的年老代这反过来跟并行算法相比吞吐量相对较低。 JVM垃圾回收时间 当年轻代内存满时会引发一次普通GC该GC仅回收年轻代。需要强调的是年轻代满是指Eden代满Survivor满不会引发GC 当老年代满时会引发Full GCFull GC将会同时回收年轻代、年老代 当永久代满时也会引发Full GC会导致Class、Method元信息的卸载 常见问题 Q为什么崩溃前垃圾回收的时间越来越长 A:根据内存模型和垃圾回收算法垃圾回收分两部分内存标记、清除复制标记部分只要内存大小固定时间是不变的变的是复制部分因为每次垃圾回收都有一些回收不掉的内存所以增加了复制量导致时间延长。所以垃圾回收的时间也可以作为判断内存泄漏的依据 Q为什么Full GC的次数越来越多 A因为内存的积累逐渐耗尽了年老代的内存导致新对象分配没有更多的空间从而导致频繁的垃圾回收 Q:为什么年老代占用的内存越来越大 A:因为年轻代的内存无法被回收越来越多地被Copy到年老代 Q:什么是串行回收和并行回收 A:串行回收是指在同一时间段内只允许一件事情发生即当多个CPU可用时也只能有一个CPU用于执行垃圾回收操作并且在执行垃圾回收时程序中的工作线程将会被暂停。当垃圾回收工作完成后才会恢复之前被暂停的工作线程这就是串行回收。 并行回收是指可以运用多个CPU同时执行垃圾回收因此提升了应用程序的吞吐量不过并行垃圾回收仍然使用了“Stop-the-World”机制和复制算法。 Q什么是并发和“Stop-the-World”机制 当通过“Stop-the-World”机制回收垃圾时垃圾收集器会在内存回收的过程中暂停程序中的所有工作线程直至完成内存回收工作后才会恢复之前被暂停的工作线程。 并发回收是指在同一时间段内应用程序的工作线程和垃圾回收线程将会同时运行或者交叉运行。 Q什么是快速分配策略 A基于线程安全的考虑如果一个类在分配内存之前已经成功完成装载步骤之后JVM就会优先选择在TLABThread Local Allocation本地线程分配缓冲区中为对象实例分配内存空间TLAB在Java堆区中是一块线程私有的区域包含在Eden空间内除了可以避免一系列的非线程安全问题外同时还能够提升内存分配的吞吐量因此我们可以将这种内存分配方式称之为快速分配策略。 Q什么是逃逸分析和栈上分配 AJava堆区已经不再是对象分配内存的唯一选择如果希望降低GC的回收平率和提升GC的回收效率那么则可以使用堆外存储技术目前最常见的堆外存储技术就是利用逃逸分析技术筛选出未发生逃逸的对象然后避开堆区而直接选择在栈帧中分配内存空间。逃逸分析是JVM在执行性能优化之前的一种分析技术它的具体目标就是分析出对象的作用域。即当一个对象被定义在方法体内部之后它的受访权限仅限于方法体内一旦其引用被外部成员引用后这个对象就发生了逃逸。反之如果定义在方法体内部的对象并没有被任何外部成员引用时JVM就会为其在栈帧中分配内存空间。 HeapOutOfMemory 当堆上分配的对象大于指定堆的最大值时抛出该错。 可以使用-XX:HeapDumpOnOutOfMemoryError 查看内存快照进行分析 MethodArea OutOfMemory 方法区内存不足存放类信息常量静态变量即时编译后的代码检查这几个信息是否有异常 大多的原因是因为动态产生过多的类。 ConstantPool OutOfMemory 常量池溢出查看是否intern使用不当 DirectMemory OutOfMemory 本机直接内存溢出容量可通过-XX:MaxDirectMemorySize指定如果不指定默认和堆最大值相同。这个溢出发生在系统进行直接内存分配。例如unsafe.allocateMemory() 特征为OOM后发现Dump问价你很小程序中直接或间接使用了NIO Stack OutOfMemory 扩展栈时无法获取足够的内存空间在创建线程时 解决方法之一减少最大堆 Stack OverFlow栈深度大于虚拟机所允许的深度经常是由于死循环的递归调用 第三章垃圾收集器和内存分配策略 1、JVM垃圾回收区域 程序计数器、虚拟机栈、本地方法栈三个区域随线程而生随线程而灭栈中的栈帧随着方法的进入和退出而有条不紊的执行着出栈和入栈操作。每一个栈帧中分配多少内存基本是在类结构确定下来时就已知的因此这三个区域的内存分配和回收都具有确定性在这三个区域内不需要过多考虑回收的问题因为方法结束或者线程结束时内存自然就跟着回收了。而java堆和方法区不一样一个接口中的多个实现类需要的内存可能不一样一个方法中的多个分支需要的内存也不一样我们只有在程序运行时才能知道会创建哪些对象这部分内存的分配和回收是动态的垃圾收集器所关注的是这部分内存。 2、引用计数算法 给对象中添加一个引用计数器每当有一个地方引用它时计数器值就加1当引用失效计数器值就减1任何时刻计数器都为0的对象就是不可能再被使用的。Java语言并没有选用引用计数器算法来管理内存其中最主要的原因就是它很难解决对象之间相互循环引用的问题。 3、根搜索算法 Java使用根搜索算法GC Root Tracing判断对象是否存活。该算法的基本思路是通过一系列的名为“GC Root”的对象作为起始点从这些节点开始向下搜索搜索所走过的路径称为引用链Reference Chain当一个对象到GC Roots没有任何引用链相连用图论的话来说就是从GC Roots到这个对象不可达时则证明此对象是不可引用的所以它们将会被判定为可回收对象。在Java语言中可作为GC Roots的对象包括下面几种 虚拟机栈栈帧中的本地变量表中的引用的对象 方法区中的类静态属性引用的对象 运行时常量池中的对象引用 方法区中的常量引用的对象 本地方法栈中JNI即一般所说的native方法引用的对象。 对象引用无论是通过引用计数器算法判断对象的引用数量还是通过根搜索算法判断对象的引用链是否可达判断对象是否存活都与“引用”有关。JDK1.2之后Java将引用分为四种强引用软引用弱引用虚引用。这四种引用强度依次逐渐减弱。 4、回收方法区 永久代方法区的垃圾收集主要回收两部分内容废弃常量和无用的类。回收废弃常量与回收Java堆中的对象非常相似。以常量池中的字面量的回收为例假如一个字符串“abc”已经进入了常量池中但是当前系统没有任何一个String对象叫做“abc”的也没有其他地方引用了这个字面量如果这个时候发生内存回收而且必要的话这个“abc”常量就会被系统“请”出常量池。常量池中的其他类接口、方法、字段的符号引用也与此类似。判断一个类是否是“无用的类”需要满足下面三个条件 该类所有的实例都已经被回收即Java堆中不存在该类的任何实例 加载该类的ClassLoader已经被回收 该类对应的java.lang.Class对象没有在任何对方被引用无法在任何地方通过反射访问该类的方法。 5、垃圾回收算法之标记-清除算法 这是最基础的收集算法。分为两个阶段标记和清除。首先标记出所有需要回收的对象在标记完成后统一回收掉所有被标记的对象。 缺点效率低下 空间问题标记清除之后会产生大量不连续的内存碎片。 6、垃圾回收算法之复制算法 该算法将内存按容量划分为大小相等的两块区域每次只使用其中的一块。当一块内存用完了就将其中还存活的对象复制到另一块区域上然后再将已经使用过的内存区域一次性清理掉。解决了内存碎片的问题。 说明现在的商业虚拟机都是采用这种收集算法来回收新生代IBM的专门研究表明新生代中的对象98%是朝生夕死的所有并不需要按照1:1的比例来划分内存空间而是将内存划分为一块较大的Eden空间和两块较小的Survivor空间每次使用Eden和其中的一块Survivor。当回收时候将Eden和Survivor中还存活的对象一次性复制到另外一块Survivor空间上最后清理掉Eden和刚刚用过的Survivor的空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8:1:1。 缺点在对象存活率较高时需要执行较多的复制操作效率将会变低老年代不能使用这种算法。 7、垃圾回收算法之标记-整理算法 根据老年代的特点有人提出了“标记-整理”算法。其中标记过程和“标记-清除”算法一样但是后续步骤不是直接对可回收的对象进行清理而是让所有存活的对象都向一端移动然后直接清理掉端边界以外的内存。 8、垃圾回收算法之分代收集算法 当前商业虚拟机的垃圾回收都是采用“分代收集”算法根据对象的存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代这样就可以根据各个年代的特点采用最适合的收集算法。在新生代中每次垃圾收集时都会发现有大量对象死去只有少量对象存活那就选择复制算法而老年代中因为对象存活率较高没有额外空间对它进行分配担保就必须采用“标记-清除”或者“标记-整理”算法来进行回收。 9、垃圾收集器之Serial收集器 Serial收集器是最基本、历史最悠久的收集器。该收集器是一个单线程的收集器即在进行垃圾收集时候必须暂停其他所有的工作线程直到它收集结束。到目前为止它依然是虚拟机运行在Client模式下的默认新生代收集器。优点是简单而高效。目前停顿时间可以控制在几十毫秒最多一百多毫秒以内。 10、垃圾收集器之G1收集器 G1(Garbage first)收集器是当前收集器技术发展的最前沿成果。G1收集器是垃圾收集器理论进一步发展的产物它与CMS收集器相比有两个显著的改进一是G1收集器是基于“标记-整理”算法实现的收集器二是它可以非常精准地控制停顿既能让使用者明确指定在一个长度为M毫秒的时间片段内消耗在垃圾收集上的时间不得超过N毫秒。 G1收集器可以实现在基本不牺牲吞吐量的前提下完成低停顿的内存回收这是由于它能够极力的避免全区域的垃圾收集G1收集器将整个Java堆包括新生代、老年代划分为多个大小固定的独立区域Region并且跟踪这些区域里面的垃圾堆积程度在后台维护一个优先列表每次根据允许的收集时间优先回收垃圾最多的区域这就是G1名称的由来。 垃圾收集器比较 垃圾收集器 算法 方式 堆区域 机制 Serial收集器 复制算法 串行 新生代 Stop-the-World Serial Old收集器 标记-压缩算法 串行 老年代 Stop-the-World ParNew收集器 复制算法 并行 新生代 Stop-the-World Parallel收集器 复制算法 并行 新生代 Stop-the-World Parallel Old收集 标记-压缩算法 并行 老年代 Stop-the-World CMS收集器 标记-清除算法 并行 老年代 Stop-the-World/并发 G1收集器 整个堆区 内存选项配置 选项 描述 备注 -Xms 设置Java堆区的初始内存 当可用的Java堆区内存小于40%时JVM就会将内存调整到选项-Xmx所允许的最大值 -Xmx 设置Java堆区的最大内存 当可用的Java堆区内存大于70%时JVM就会将内存调整到选项-Xms所指定的初始值 -Xmn 设置新生代(YoungGen)的内存 -Xmn的内存大小为Eden2个Surivivor空间的值官方建议配置为整个堆的3/8 -XX:NewSize 设置新生代(YoungGen)的初始内存 和选项-Xmn等价但是推荐使用-Xmn相当于一次性设定了NewSize/Max-NewSize的内存大小 -XX:MaxNewSize 设置新生代(YoungGen)的最大内存 -XX:NewRatio 新生代(Eden2个Surivivor空间)与老年代的比值不包括永久代 选项-XX:NewRatio4时表示新生代与老年代所占的比值为1:4。如果已经设置了选项-Xmn则无需设置该选项 -XX:PermSize 设置方法区的初始内存 -XX:MaxPermSize 设置方法区的最大内存 -XX:SurivivorRatio Eden空间与2个Surivivor空间的比值大小 Eden空间和另外2个Surivivor空间缺省所占的比值为8:1 -XX:TLABWasteTargetPercent 设置TLAB空间所占用Eden空间的百分比大小 GC组合配置 GC组合 Minor GC Full GC 描述 -XX:UserSerialGC Serial收集器串行回收 Serial Old收集器串行回收 选项-XX:UseSerialGC 可以手动指定使用Serial收集器Serial Old收集器组合执行内存回收 -XX:UseParNewGC ParNew收集器并行回收 Serial Old收集器串行回收 选项-XX:UseParNewGC可以手动指定使用ParNew收集器Seral Old收集器组合执行内存回收 -XX:UseParallelGC Parallel收集器并行回收 Serial Old收集器串行回收 通过-XX:UseParallelGC可以手动指定使用Parallel收集器和Serial Old收集器组合执行内存回收 -XX:UseParallelOldGC Parallel收集器并行回收 Parallel Old收集器并行回收 通过-XX:UseParallelOldGC可以手动指定使用Parallel收集器和Parallel Old收集器组合执行内存回收 -XX:UseConcMarkSweepGC ParNew收集器并行回收 缺省使用CMS收集器并发执行回收备用采用Serial Old收集器串行回收 使用-XX:UseConcMarkSweepGC可以手动指定使用ParNew收集器CMS收集器Serial Old收集器组合执行内存回收。优先使用ParNewCMS组合当出现ConcurrentNode Failure或者Promotion Failed时则采用ParNewSerial Old组合。 -XX:UseConcMarkSweepGC -XX:UseParNewGC Serial 收集器串行回收 -XX:UseG1GC G1收集器并发、并行的内存回收 第七章虚拟机类加载机制 1、虚拟机的类加载机制 虚拟机把描述类的数据从Class文件加载到内存中并对数据进行校验、转换解析和初始化最终形成可以被虚拟机直接使用的Java类型这就是虚拟机的类加载机制。 2、类被加载到虚拟机经过的7个阶段 类从被加载到虚拟机内存中开始到卸载出内存为止它的整个生命周期包括了加载、校验、准备、解析、初始化、使用和卸载七个阶段。其中校验/验证、准备和解析三个部分统称为连接。 3、何时进行类的初始化 虚拟机规范严格规定了有且只有四种情况必须立即对类进行初始化而加载、校验、准备和解析自然需要在初始化之前开始 1遇到new、getstatic、putstatic、或者这4条字节码指令时invokestatic如果类没有进行初始化则需要先触发其初始化生成这4条指令最常见的Java代码场景是使用new关键字实例化对象的时候、读取或者设置一个类的静态字段被final修饰、已经在编译期把结果放入常量池的静态字段除外的时候以及调用一个类的静态方法的时候 2使用java.lang.reflect包的方法对类进行反射调用的时候如果类没有进行过初始化则需要先触发其初始化 3当初始化一个子类的时候如果发现其父类还没有进行过初始化则需要先触发其父类的初始化 4当虚拟机启动时用户需要指定一个要执行的主类包含main方法的那个类虚拟机会先初始化这个主类。 对于静态字段只有直接定义这个字段的类才会被初始化因此通过其子类来引用父类中定义的静态字段只会触发其父类的初始化而不会触发子类的初始化。 4、加载 在加载阶段虚拟机需要完成以下三件事情 通过一个类的全限定名来获取定义此类的二进制字节流 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构 在Java堆中生成一个代表这个类的java.lang.Class对象作为方法区这些数据的访问入口。 加载阶段完成后虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中。然后在java堆中实例化一个java.lang.Class对象这个对象将作为程序访问方法区中的这些类型数据的外部接口加载阶段和连接阶段的部分内容如一部分字节码文件格式验证动作是交叉进行的加载阶段尚未完成连接阶段可能已经开始但是这些夹在加载阶段之中的动作仍然属于连接阶段的内容这两个阶段的开始时间仍然保持着固定的先后顺序。 5、验证 验证是连接阶段的第一步这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求并且不会危害虚拟机自身的安全。 虚拟机验证过程的四个阶段 文件格式验证 元数据验证 字节码验证 符号引用验证。 6、准备 准备阶段是正式为类变量分配内存并设置类变量初始值的阶段这些内存都将在方法区中进行分配。这个阶段中有两个容易产生混淆的概念首先是这时候进行内存分配的仅包含类变量被static修饰的变量而不包含实例变量实例变量将会在对象实例化时随着对象一起分配在Java堆中。其次是这里所说的初始值“通常情况”下是数据类型的零值假设一个类变量的定义为public static int value123;那么变量value在准备阶段过后的初始值为0而不是123。 7、解析: 解析阶段是虚拟机将常量池内的符号引用替换成直接引用的过程。 符号引用符号引用以一组符号来描述所引用的目标符号可以是任何形式的字面量只要使用时能无歧义的定位到目标即可。符号引用与虚拟机实现的内存布局无关。引用的目标并不一定已经加载到内存中。 直接引用直接引用可以是直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄。直接引用是与虚拟机实现的内存布局相关的同一符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同。 7、类与类加载器 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取此类的二进制字节流”这个动作放到Java虚拟机外部去实现以便让应用程序自己决定如何去获取所修要的类。实现这个动作的代码模块被称为“类加载器”。 类加载器虽然只用于实现类的加载动作但它在Java程序中起到的作用却远远不限于类加载阶段。对于任意一个类都需要由加载它的类加载器和这个类本身一同确定其在Java虚拟机中的唯一性。 8、双亲委派模型 绝大部分Java程序都会使用到以下三种系统提供的类加载器 1启动类加载器BootStrap ClassLoader在HotSpot虚拟机中这个类加载器由C语言实现是虚拟机自身的一部分。它负责将存放在JAVA_HOME\lib目录中的并且是虚拟机标识的仅按照文件名识别如rt.jar名称不符合的类库即使放在lib目录中也不会被加载类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用。 2扩展类加载器Extention ClassLoader这个加载器有sun.misc.Launcher$ExtClassLoader实现。它负责加载JAVA_HOME/lib/ext目录中的或者被java.ext.dirs系统变量所指定的路径中的所有类库开发者可以直接使用扩展类加载器。 3应用程序类加载器Application ClassLoader这个类加载器由sun.misc.Launcher$AppClassLoader来实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值所以一般也称它为系统类加载器。它负责加载用户类路径ClassPath上所指定的类库。如果应用程序没有指定自定义的类加载器一般情况下这个就是程序中默认的类加载器。 我们的应用程序都是由这三个类加载器互相配合进行加载的。 双亲委派模型的工作过程如果一个类加载器收到了类加载的请求它首先不会自己去尝试加载这个类而是把这个请求委托给父类加载器去完成。每一个层次的类加载器都是如此因此所有的加载请求最终都应该传递到顶层的启动类加载器中只有当父加载器反馈自己无法完成这个加载请求它的搜索范围中没有找到所需加载的类时子加载器才会自己尝试去加载。 当一个Java程序响应很慢时如何查找问题 转载于:https://www.cnblogs.com/wrong5566/p/6531832.html