本文目录一览:
alert报错stackoverflowerror原因
每一个JVM线程都拥有一个私有的JVM线程栈,用于存放当前线程的JVM栈帧(包括被调用函数的参数、局部变量和返回地址等)。如果某个线程的线程栈空间被耗尽,没有足够资源分配给新创建的栈帧,就会抛出java.lang.StackOverflowError错误。
引发StackOverFlowError的常见原因有以下几种:
·无限递归循环调用(最常见)。
·执行了大量方法,导致线程栈空间耗尽。
·方法内声明了海量的局部变量。
·native代码有栈上分配的逻辑,并且要求的内存还不小,比如java.net.SocketInputStream.read0会在栈上要求分配一个64KB的缓存(64位Linux)。
除了程序抛出StackOverflowError错误以外,还有两种定位栈溢出的方法:
·进程突然消失,但是留下了crash日志,可以检查crash日志里当前线程的stack范围,以及RSP寄存器的值。如果RSP寄存器的值超出这个stack范围,那就说明是栈溢出了。
·如果没有crash日志,那只能通过coredump进行分析。在进程运行前,先执行ulimit-cunlimited,当进程挂掉之后,会产生一个core.[pid]的文件,然后再通过jstack$JAVA_HOME/bin/javacore.[pid]来看输出的栈。如果正常输出了,那就可以看是否存在很长的调用栈的线程,当然还有可能没有正常输出的,因为jstack的这条从core文件抓栈的命令其实是基于ServiceabilityAgent实现的,而SA在某些版本里有Bug。
常见的解决方法包括以下几种:
·修复引发无限递归调用的异常代码,通过程序抛出的异常堆栈,找出不断重复的代码行,按图索骥,修复无限递归Bug。
·排查是否存在类之间的循环依赖。
·排查是否存在在一个类中对当前类进行实例化,并作为该类的实例变量。
·通过JVM启动参数-Xss增加线程栈内存空间,某些正常使用场景需要执行大量方法或包含大量局部变量,这时可以适当地提高线程栈空间限制,例如通过配置-Xss2m将线程栈空间调整为2mb。
6个重要的JVM性能参数
围绕垃圾收集和内存,您可以将600多个参数传递给 JVM 。如果包括其他方面,则JVM参数总数将很容易超过1000+。任何人都无法消化和理解太多的论据。在本文中,重点介绍了七个重要的 JVM 参数,在 Java性能测试 中起着非常重要的作用。
-Xmx 可能是最重要的 JVM 参数。 -Xmx 定义要分配给应用程序的最大堆大小。。您可以这样定义应用程序的堆大小: -Xmx2g 。
堆大小在影响应用性能和所需物理硬件需求。这带来了一个问题,我的应用程序正确的堆大小是多少?我应该为应用程序分配大堆大小还是小堆大小?答案是:取决于需求和预算。
将 -Xms 和 -Xmx 设置为相同值的会提高JVM性能
元空间是将存储 JVM 的元数据定义(例如类定义,方法定义)的区域。默认情况下,可用于存储此元数据信息的内存量是无限的(即受您的容器或计算机的RAM大小的限制)。您需要使用 -XX:MaxMetaspaceSize 参数来指定可用于存储元数据信息的内存量的上限。
-XX:MaxMetaspaceSize=256m
OpenJDK中有7种不同的GC算法:
如果您未明确指定GC算法,那么JVM将选择默认算法。在Java 8之前, Parallel GC 是默认的GC算法。从Java 9开始, G1 GC 是默认的GC算法。
GC算法的选择对于确定应用程序的性能起着至关重要的作用。根据我们的研究,我们正在使用Z GC算法观察到出色的性能结果。如果使用 JVM 11+ ,则可以考虑使用 Z GC 算法(即 -XX:+ UseZGC )。
下表总结了激活每种垃圾收集算法所需传递的JVM参数。
垃圾收集日志包含有关垃圾收集事件,回收的内存,暂停时间段等信息,可以通过传递以下JVM参数来启用垃圾收集日志:
从JDK 1到JDK 8:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:{file-path}
从JDK 9及更高版本开始:
-Xlog:gc*:file={file-path}
Demo:
通常,GC日志用于调整垃圾回收性能。但是,GC日志包含重要的微观指标。这些指标可用于预测应用程序的可用性和性能特征。在本文中将重点介绍一种这样的标尺:GC吞吐量。GC吞吐量是您的应用程序在处理客户交易中花费的时间与它在处理GC活动中花费的时间之比。假设您的应用程序的GC吞吐量为98%,则意味着应用程序将其98%的时间用于处理客户活动,其余2%用于GC活动。
现在,让我们看一个健康的JVM的堆使用情况图:
您会看到一个完美的锯齿图案。您会注意到,当运行Full GC(红色三角形)时,内存利用率将一直下降到最低。
现在,让我们看一下有问题的JVM的堆使用情况图:
您可以注意到,在图表的右端,即使GC反复运行,内存利用率也没有下降。这是一个典型的内存泄漏迹象,表明该应用程序正在存在某种内存问题。
如果您仔细观察一下该图,您会发现重复的完整GC开始在上午8点左右开始。但是,该应用程序仅在上午8:45左右开始获取OutOfMemoryError。到上午8点,该应用程序的GC吞吐量约为99%。但是,在上午8点之后,GC吞吐量开始下降到60%。因为当重复的GC运行时,该应用程序将不会处理任何客户交易,而只会进行GC活动。
OutOfMemoryError 是一个严重的问题,它将影响您的应用程序的可用性和性能。要诊断 OutOfMemoryError 或任何与内存相关的问题,必须在应用程序开始遇到 OutOfMemoryError 的那一刻或一瞬间捕获堆转储。由于我们不知道何时会抛出 OutOfMemoryError ,因此很难在抛出时左右的正确时间手动捕获堆转储。但是,可以通过传递以下JVM参数来自动化捕获堆转储:
-XX:+ HeapDumpOnOutOfMemoryError和-XX:HeapDumpPath = {HEAP-DUMP-FILE-PATH}
在 -XX:HeapDumpPath 中,需要指定堆转储所在的文件路径。传递这两个JVM参数时,将在抛出 OutOfMemoryError 时自动捕获堆转储并将其写入定义的文件路径。例:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof
一旦捕获了堆转储,就可以使用 HeapHero 和 EclipseMAT 之类的工具来分析堆转储。
每个应用程序将具有数十,数百,数千个线程。每个线程都有自己的堆栈。在每个线程的堆栈中,存储以下信息:
他们每个都消耗内存。如果它们的使用量超出某个限制,则会引发 StackOverflowError 。可以通过传递-Xss参数来增加线程的堆栈大小限制。例:
-Xss256k
如果将此 -Xss 值设置为一个很大的数字,则内存将被阻塞并浪费。假设您将 -Xss 值指定为 2mb ,而只需要 256kb ,那么您将浪费大量的内存。
假设您的应用程序有500个进程,然后 -Xss 值为 2Mb ,则您的线程将消耗 1000Mb 的内存。另一方面,如果您仅将 -Xss 分配为 256kb ,那么您的线程将仅消耗 125Mb 的内存。每个JVM将节省 875Mb 内存。
注意:线程是在堆(即 -Xmx )之外创建的,因此这 1000Mb 将是您已经分配的-Xmx值的补充。
现代应用程序使用多种协议(即SOAP,REST,HTTP,HTTPS,JDBC,RMI)与远程应用程序连接。有时远程应用程序可能需要很长时间才能做出响应,有时它可能根本不响应。
如果没有正确的超时设置,并且远程应用程序的响应速度不够快,则您的应用程序线程/资源将被卡住。远程应用程序无响应可能会影响您的应用程序的可用性。它可以使您的应用程序停止磨削。为了保护应用程序的高可用性,应配置适当的超时设置。
您可以在JVM级别传递这两个强大的超时网络属性,这些属性可以全局适用于所有使用 java.net.URLConnection 的协议处理程序:
sun.net.client.defaultConnectTimeout :指定建立到主机的连接的超时(以毫秒为单位)。例如,对于HTTP连接,它是与HTTP服务器建立连接时的超时。当建立与资源的连接时, sun.net.client.defaultReadTimeout 指定从输入流读取时的超时(以毫秒为单位)。
例如,如果您要将这些属性设置为2秒:
注意,默认情况下,这两个属性的值为-1,这表示未设置超时。
JVM creation failed 怎么解决
在NetBeans的安装目录下有一个etc文件夹,下面有一个netbeans.conf文件,这个文件就是NetBeans的启动配置文件,打开文件内容如下:
# ${HOME} will be replaced by JVM user.home system property
netbeans_default_userdir="${HOME}/.netbeans/7.0beta"
# Options used by NetBeans launcher by default, can be overridden by explicit
# command line switches:
netbeans_default_options="-J-client -J-Xss2m -J-Xms32m -J-XX:PermSize=32m -J-XX:MaxPermSize=384m -J-Dnetbeans.logger.console=true -J-ea -J-Dapple.laf.useScreenMenuBar=true -J-Dapple.awt.graphics.UseQuartz=true -J-Dsun.java2d.noddraw=true"
# Note that a default -Xmx is selected for you automatically.
# You can find this value in var/log/messages.log file in your userdir.
# The automatically selected value can be overridden by specifying -J-Xmx here
# or on the command line.
# If you specify the heap size (-Xmx) explicitely, you may also want to enable
# Concurrent Mark Sweep garbage collector. In such case add the following
# options to the netbeans_default_options:
# -J-XX:+UseConcMarkSweepGC -J-XX:+CMSClassUnloadingEnabled -J-XX:+CMSPermGenSweepingEnabled
# (see )
# Default location of JDK, can be overridden by using --jdkhome dir:
netbeans_jdkhome="D:/Java/jdk1.6.0_16"
# Additional module clusters, using ${path.separator} (';' on Windows or ':' on Unix):
#netbeans_extraclusters="/absolute/path/to/cluster1:/absolute/path/to/cluster2"
# If you have some problems with detect of proxy settings, you may want to enable
# detect the proxy settings provided by JDK5 or higher.
# In such case add -J-Djava.net.useSystemProxies=true to the netbeans_default_options.
该配置文件中以“#”开头的行均为注释,因此重点关注未以“#”开头的行。
第一行“netbeans_default_userdir”,定义了用户关于NetBeans的设置保存的位置。
第二行“netbeans_default_options”,这后面的参数包括了Java虚拟机启动时的一些设置以及NetBeans启动时的一些设置。(问题应该就在这里了。)
第三行“netbeans_jdkhome”,这里定义了NetBeans所使用的JDK所在的位置。
在“netbeans_default_options”后的参数中,有一条“-J-MaxPermSize=384m”,这里定义了Java虚拟机能使用的堆栈的最大值为384m,最后经过多次修改尝试,将其值改为300m就可以了。