java怎么增加堆栈_如何增加Java堆栈大小?「建议收藏」

java怎么增加堆栈_如何增加Java堆栈大小?「建议收藏」如何增加Java堆栈大小?我问了这个问题,以了解如何增加JVM中的运行时调用堆栈大小。我已经得到了一个答案,而且我也得到了很多有用的答案和评论,这些答案和评论与Java如何处理需要大型运行时堆栈的情况相关。我已经回答了问题的总结。最初我想增加JVM堆栈的大小,所以像没有StackOverflowError运行的程序。publicclassTT{publicstaticlongfa…

大家好,又见面了,我是你们的朋友全栈君。

如何增加Java堆栈大小?

我问了这个问题,以了解如何增加JVM中的运行时调用堆栈大小。 我已经得到了一个答案,而且我也得到了很多有用的答案和评论,这些答案和评论与Java如何处理需要大型运行时堆栈的情况相关。 我已经回答了问题的总结。

最初我想增加JVM堆栈的大小,所以像没有StackOverflowError运行的程序。

public class TT { public static long fact(int n) { return n < 2 ? 1 : n * fact(n – 1); } public static void main(String[] args) { System.out.println(fact(1 << 15)); } }

相应的configuration设置是具有足够大的值的java -Xss…命令行标志。 对于上面的程序TT ,它可以像OpenJDK的JVM一样工作:

$ javac TT.java $ java -Xss4m TT

其中一个答案也指出-X…标志是依赖于实现的。 我正在使用

java version “1.6.0_18” OpenJDK Runtime Environment (IcedTea6 1.8.1) (6b18-1.8.1-0ubuntu1~8.04.3) OpenJDK 64-Bit Server VM (build 16.0-b13, mixed mode)

也可以为一个线程指定一个大堆栈(请参阅其中一个答案)。 这是比java -Xss…推荐,以避免浪费内存的线程不需要它。

我很好奇上面的程序需要多大的堆栈,所以我运行它增加了:

-Xss4m可以满足fact(1 << 15)

-Xss5m可以满足fact(1 << 17)

-Xss7m可以满足fact(1 << 18)

-Xss9m可以满足fact(1 << 19)

-Xss18m可以满足fact(1 << 20)

-Xss35m可以满足fact(1 << 21)

-Xss68m可以满足fact(1 << 22)

-Xss129m可以满足fact(1 << 23)

-Xss258m可以满足fact(1 << 24)

-Xss515m可以满足fact(1 << 25)

从上面的数字看来,Java对于上面的函数使用每个栈帧大约16个字节,这是合理的。

上面的枚举包含的可以 是足够的 ,因为堆栈需求是不确定的:使用相同的源文件多次运行它,相同的-Xss…有时成功,有时会产生StackOverflowError 。 例如,对于1 20, -Xss18m已经足够用于10次中的7次,并且-Xss19m也不总是足够的,但是-Xss20m已经足够了(100次全部100次)。 垃圾收集,JIT踢,或其他事情导致这种不确定的行为?

在StackOverflowError打印的堆栈跟踪(可能还有其他例外情况)只显示运行时堆栈的最新的1024个元素。 下面的答案演示了如何计算到达的确切深度(可能比1024大很多)。

许多回应者指出,考虑替代的,相同algorithm的较less堆栈实现是一个好的和安全的编码实践。 一般来说,可以将一组recursion函数转换为迭代函数(使用例如Stack对象,而不是在运行时栈上填充)。 对于这个特定的factfunction,转换它是相当容易的。 我的迭代版本如下所示:

public class TTIterative { public static long fact(int n) { if (n < 2) return 1; if (n > 65) return 0; // Enough powers of 2 in the product to make it (long)0. long f = 2; for (int i = 3; i <= n; ++i) { f *= i; } return f; } public static void main(String[] args) { System.out.println(fact(1 << 15)); } }

仅供参考,正如上面的迭代解决scheme所示, fact函数无法计算65以上(实际上,甚至高于20)的确切因子数,因为Java内置typeslong会溢出。 重构的fact所以它会返回一个BigInteger而不是long也会产生大input的确切结果。

嗯…它适用于我和远远less于999MB的堆栈:

> java -Xss4m Test 0

(Windows JDK 7,构build17.0-b05客户端VM和Linux JDK 6 – 与您发布的版本相同)

我假设你计算堆栈跟踪中的循环线的“深度1024”? 显然,Throwable中的堆栈跟踪数组长度似乎被限制为1024,请尝试以下程序:

public class Test { public static void main(String[] args) { try { System.out.println(fact(1 << 15)); } catch (StackOverflowError e) { System.err.println(“true recursion level was “+level); System.err.println(“reported recursion level was “+e.getStackTrace().length); } } private static int level = 0; public static long fact(int n) { level++; return n < 2 ? n : n * fact(n – 1); } }

如果你想玩线程堆栈大小,你需要看看热点JVM上的-Xss选项。 在非热点虚拟机上可能有些不同,因为到JVM的-X参数是特定于分布的,IIRC。

在热点上,如果你想把大小设置为16兆,这看起来像java -Xss16M 。

inputjava -X -help如果你想查看所有可以传入的特定于分发的JVM参数。我不确定这是否和其他JVM一样,但是它打印所有的热点特定参数。

对于它的价值 – 我会build议限制你在Java中使用recursion方法。 在优化它们时不是太好,因为JVM不支持尾recursion(请参阅JVM是否阻止尾调用优化? )。 尝试重构上面的因子代码,以使用while循环而不是recursion方法调用。

控制进程内堆栈大小的唯一方法是启动一个新的线程。 但是你也可以用-Xss参数创build一个自调用的子java进程。

public class TT { private static int level = 0; public static long fact(int n) { level++; return n < 2 ? n : n * fact(n – 1); } public static void main(String[] args) throws InterruptedException { Thread t = new Thread(null, null, “TT”, 1000000) { @Override public void run() { try { level = 0; System.out.println(fact(1 << 15)); } catch (StackOverflowError e) { System.err.println(“true recursion level was ” + level); System.err.println(“reported recursion level was ” + e.getStackTrace().length); } } }; t.start(); t.join(); try { level = 0; System.out.println(fact(1 << 15)); } catch (StackOverflowError e) { System.err.println(“true recursion level was ” + level); System.err.println(“reported recursion level was ” + e.getStackTrace().length); } } }

因为你急于避免一切合理的方法,所以很难给出一个合理的解决scheme。 重构一行代码是可行的解决scheme。

注意:使用-Xss设置每个线程的堆栈大小,这是一个非常糟糕的主意。

另一种方法是通过字节码操作来更改代码,如下所示:

public static long fact(int n) { return n < 2 ? n : n > 127 ? 0 : n * fact(n – 1); }

因为n> 127的每个答案都是0.这样可以避免更改源代码。

添加此选项

–driver-java-options -Xss512m

到你的spark-submit命令将解决这个问题。

奇怪的! 你说你想要产生1 << 15深度 ???的recursion !

我build议不要尝试它。 堆栈的大小将是2^15 * sizeof(stack-frame) 。 我不知道堆栈大小是多less,但2 ^ 15是32.768。 呃,如果它在1024(2 ^ 10)的时候停下来的话,你将不得不把它做成2 ^ 5倍,比你的实际设置大32倍。

其他海报已经指出如何增加记忆,你可以记忆电话。 我build议,对于许多应用程序,你可以使用斯特林公式近似大n! 几乎没有内存占用。

在这篇文章中,有一些分析function和代码:

我做了Anagram excersize ,这就像Count Change问题,但有5万面值(硬币)。 我不确定它可以迭代完成 ,我不在乎。 我只知道-xss选项没有任何作用 – 我总是在1024个堆栈帧之后失败(可能是scala没有把工作交给java或printStackTrace限制,我不知道)。 无论如何,这是不好的select。 你不希望所有的线程在应用程序是可怕的。 但是,我做了一些新的线程(堆栈大小)的实验。 这确实有效,

def measureStackDepth(ss: Long): Long = { var depth: Long = 0 val thread: Thread = new Thread(null, new Runnable() { override def run() { try { def sum(n: Long): Long = {depth += 1; if (n== 0) 0 else sum(n-1) + 1} println(“fact = ” + sum(ss * 10)) } catch { case e: StackOverflowError => // eat the exception, that is expected } } }, “deep stack for money exchange”, ss) thread.start() thread.join() depth } //> measureStackDepth: (ss: Long)Long for (ss measureStackDepth((scala.math.pow (10, ss)).toLong) ) //> fact = 10 //| (ss = 10^0 allows stack of size ,11) //| fact = 100 //| (ss = 10^1 allows stack of size ,101) //| fact = 1000 //| (ss = 10^2 allows stack of size ,1001) //| fact = 10000 //| (ss = 10^3 allows stack of size ,10001) //| (ss = 10^4 allows stack of size ,1336) //| (ss = 10^5 allows stack of size ,5456) //| (ss = 10^6 allows stack of size ,62736) //| (ss = 10^7 allows stack of size ,623876) //| (ss = 10^8 allows stack of size ,6247732) //| (ss = 10^9 allows stack of size ,62498160)

您会发现堆栈可以以指数级更多的堆栈分配给线程,从而成倍地增长。

试试jvm参数:-Xmx128m

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/156364.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月7日 上午11:36
下一篇 2022年7月7日 上午11:46


相关推荐

  • Android抓包工具——Fiddler

    Android抓包工具——Fiddler前言 在平时和其他大佬交流时 总会出现这么些话 抓个包看看就知道哪出问题了 抓流量啊 payload 都在里面 这数据流怎么这么奇怪 这里出现的名词 其实都是差不多的意思啊 这都跟抓包这个词有关 说到抓包呢我们今天就先来了解一下抓包的一些基础定义跟抓包工具 Fiddler 的使用跟安装吧 本篇文章 博主只想使用通俗易懂的话语 让大家明白以下内容 什么是抓包哪些场景需要用到抓包 Fiddler 抓包的原理怎样使用 Fiddler 进行移动端抓包抓包包 Packet 是 T

    2026年3月20日
    3
  • nbtscan工具

    nbtscan工具这是一款用于扫描 Windows 网络上 NetBIOS 名字信息的程序 该程序对给出范围内的每一个地址发送 NetBIOS 状态查询 并且以易读的表格列出接收到的信息 对于每个响应的主机 NBTScan 列出它的 IP 地址 NetBIOS 计算机名 登录用户名和 MAC 地址 但只能用于局域网 NBTSCAN 可以取到 PC 的真实 IP 地址和 MAC 地址 如果有 ARP 攻击 在做怪 可以找到装有 ARP 攻击的 PC 的 IP 和 MA

    2026年3月26日
    2
  • 使用JAX-WS构建Web Services

    使用JAX-WS构建Web Services 使用JAX-WS构建WebServicesJAX-WS简写为JavaApiForXmlWebService。JAX-WS是使用XML构建WebService与Client进行交流通信的技术。在JAX-WS中,WebService操作调用表现为以XML为基础的协议如SOAP协议。SOAP定义了封装架构,编码规则以及WebService中调用和回应表现的规则。这些调用和

    2022年7月15日
    15
  • sql语法:inner join on, left join on, right join on具体用法

    sql语法:inner join on, left join on, right join on具体用法

    2021年12月15日
    66
  • 深度学习中的自动编码器:TensorFlow示例

    深度学习中的自动编码器:TensorFlow示例什么是自动编码器?  自动编码器是重建输入的绝佳工具。简单来说,机器就是一个图像,可以生成一个密切相关的图片。这种神经网络中的输入是未标记的,这意味着网络能够在没有监督的情况下进行学习。更准确地说,输入由网络编码,仅关注最关键的特征。这是自动编码器因降维而流行的原因之一。此外,自动编码器可用于生成生成学习模型。例如,神经网络可以用一组面部训练,然后可以产生新的面部。Autoencoder如何工…

    2022年6月3日
    46
  • 安装错误 INSTALL_PARSE_FAILED_MANIFEST_MALFORMED 解决办法「建议收藏」

    安装错误 INSTALL_PARSE_FAILED_MANIFEST_MALFORMED 解决办法「建议收藏」安装时提示错误:Failure[INSTALL_PARSE_FAILED_MANIFEST_MALFORMED]是AndroidManifest.xml文件配置错误,有两种情况:1、Activity路径前面没有加点。2、taskAffinity属性前面没有加点。

    2025年5月27日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号