首页 > 编程知识 正文

javajvm调优有几种方法,linux运行java文件

时间:2023-05-03 15:03:49 阅读:23795 作者:630

序言:

文章输出来源:检查Java高薪训练营进行教育。

本文是学习课程课后笔记的一部分

一. JVM优化

1. JVM概述

image.png

JVM是Javavirtualmachine(Java虚拟机)的缩写,JVM是计算设备的规范,是通过在实际计算机上模拟各种计算机功能实现的虚构计算机

JVM是Java程序可以执行的核心。 但是请注意,JVM自己什么也做不了,所以需要提供生产原料(.class文件)。 只有JVM一次也不能编译,而且在任何地方运行。 需要基本类库,包括如何处理文件,如何连接到网络。

JVM标准和实现的一大堆基础类库构成了Java的运行时环境,即常见的javaruntimeenvironment (JRE )。

对JDK(Javadevelopmentkit )来说更庞大了。 除了JRE,JDK还提供了非常易于使用的小工具,如javac、java和jar。

JVM、JRE和JDK这三种关系可以用一个包含关系表示。

image.png

2 .整个JVM体系结构

根据JVM规范,JVM内存分为五个部分:虚拟机堆栈、堆、方法区域、程序计数器和本地方法堆栈。

image.png

image.png

JVM分为五个模块:类加载器子系统、运行时数据区、执行引擎、本地方法接口和垃圾回收。

image.png

JDK7和JDK8更改

image.png

线程私有:程序计数器虚拟机堆栈本地方法堆栈

线程共享:堆方法空间直接内存(非运行时数据区的一部分) )。

方法区域Java8以后的变化

删除“永久”(PermGen )并将其替换为元空间)

永久世代的类元信息(class metadata )已迁移到本机内存(native memory )而不是虚拟机

永久层代的interned Strings (字符串常量池)和class static variables类静态变量)已迁移到Java heap

永久参数(PermSize MaxPermSize ) -元空间参数(MetaspaceSize MaxMetaspaceSize )

Java8为什么要用Metaspace替换永久替代?

字符串存在于永久世代中,容易发生性能问题和内存溢出。

类和方法的信息等很难确定大小,因此很难指定持久层代的大小,过小时容易发生持久层代溢出,过大时容易发生老层代溢出。

永久世代给GC带来不必要的复杂性,回收效率低。

甲骨文可能会将热点和JRockit合二为一,但JRockit没有永久一代。

二. OutOfMemoryError异常

1. Java堆溢出

堆中主要存储对象、数组等,如果不断创建这些对象,并确保GC Roots到对象之间的路径可用,从而避免垃圾回收机制清除这些对象

/**设置最大堆的最小堆:-Xms20m -Xmx20m */

公共类heap oom {

静态类oom对象{

}

publicstaticvoidmain (字符串[ ] args {

List oomObjectList=new ArrayList (;

while(true ) oomobjectlist.add (newoomobject ) );

}

}

}

执行后报告异常,堆栈信息可见:

有关Java.lang.out of memory error : javaheapspace的信息,请参见,

说明堆内存空间中发生内存溢出的异常。

新生成的对象首先分配给新生代,新生代满时进行一次Minor GC,Minor GC后将该对象和新生代满足条件的对象放入旧年代,旧年代空间不够时进行Full GC

一般理由:

中加载的数据太多。 例如,一次从数据库中检索太多数据

集合使用了太多对对象的引用

完后没有清空;

代码中存在死循环或循环产生过多重复对象;

堆内存分配不合理

2. 虚拟机栈和本地方法栈溢出

由于HotSpot虚拟机中并不区分虚拟机栈和本地方法栈, 因此对于HotSpot来说, -Xoss参数(设置本地方法栈大小) 虽然存在, 但实际上是没有任何效果的, 栈容量只能由-Xss参数来设定。

常见原因:

1) 如果线程请求的栈深度大于虚拟机所允许的最大深度, 将抛出StackOverflowError异常。

2) 如果虚拟机的栈内存允许动态扩展, 当扩展栈容量无法申请到足够的内存时, 将抛出OutOfMemoryError异常。

对于不同版本的Java虚拟机和不同的操作系统, 栈容量最小值可能会有所限制, 这主要取决于操 作系统内存分页大小。

譬如参数-Xss128k可以正常用于32位Windows系统下的JDK 6, 但是如果用于64位Windows系统下的JDK 11, 则会提示栈容量最小不能低于180K, 而在Linux下这个值则 可能是228K, 如果低于这个最小限制, HotSpot虚拟器启动时会给出如下提示:

The Java thread stack size specified is too small. Specify at least 228k

3. 运行时常量池和方法区溢出

在JDK 6或更早之前的HotSpot虚拟机中, 常量池都是分配在永久代中;

我们可以通过-XX: PermSize和-XX: MaxPermSize限制永久代的大小, 即可间接限制其中常量池的容量。

自JDK 7起, 原本存放在永久代的字符串常量池被移至Java堆之中,不容易溢出。

方法区的主要职责是用于存放类型的相关信息, 如类名、 访问修饰符、 常量池、 字段

描述、 方法描述等。

方法区溢出:方法区运行时产生大量的类。

一个类如果要被垃圾收集器回收, 要达成的条件是比较苛刻的。

在经常运行时生成大量动态类的应用场景里, 就应该特别关注这些类的回收状况。

这类场景除了使用了CGLib字节码增强和动态语言外, 常见的还有: 大量JSP或动态产生JSP 文件的应用(JSP第一次运行时需要编译为Java类) 、 基于OSGi的应用(即使是同一个类文件, 被不同的加载器加载也会视为不同的类)等。

4. 直接内存溢出

直接内存(Direct Memory) 的容量大小可通过-XX: MaxDirectMemorySize参数来指定, 如果不去指定, 则默认与Java堆最大值(由-Xmx指定) 一致;

由直接内存导致的内存溢出, 一个明显的特征是在Heap Dump文件中不会看见有什么明显的异常情况, 如果发现内存溢出之后产生的Dump文件很小, 而程序中又直接或间接使用了 DirectMemory(典型的间接使用就是NIO) ,那就可以考虑重点检查一下直接内存方面的原因了。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。