【问题标题】:Java size of an Exception in memory内存中异常的 Java 大小
【发布时间】:2014-01-29 04:03:19
【问题描述】:

有谁知道异常一旦被创建和抛出占用多少内存?

例如,NullPointerException

以及异常是如何被垃圾收集的?

【问题讨论】:

  • 它们像任何其他 Java 对象一样被收集。为什么他们会有什么特别之处?
  • 异常的大小将取决于您的 Java 实现和调用堆栈的深度。你需要这些信息做什么?你可能不应该有无数的例外,所以大部分时间都无关紧要。
  • 我完全同意马克,这应该是你问题的答案
  • 我认为垃圾收集的问题是有道理的。当然,一个异常对象在不再引用它之后会被垃圾回收。但是什么时候达到这个条件呢?对象的存活时间是多少?传统上,您不会将其分配给范围清晰可见的变量。
  • @BogdanT。它存在于内存中,直到它被捕获然后超出范围/不再持有引用,或者它未被捕获并且由于未捕获的异常而停止了主线程。

标签: java exception memory nullpointerexception


【解决方案1】:

有谁知道异常创建和抛出后占用了多少内存?

这完全取决于例外情况。像任何其他对象一样,它包含可变数量的数据;如果有人做了傻事,String 消息可能是 4MB:

Exception e = 
    new Exception(new String("Some gigantic message ... lalalalalalalalla"));

(编辑: 好的,这有点误导;异常包含对 String 的引用,并且引用值是固定大小,但 String 本身可能只被异常 - 我将其更改为非文字,以明确表明它可能是可收藏的。自定义异常可以包含任何东西,但它是一个像任何其他对象一样的对象。此外,它取决于 far 它已被抛出,因为它在其中保存堆栈跟踪。SO 上有一个很好的 Q/A;In java, what is the best way to determine the size of an object 涵盖了这一点。)

以及异常是如何被垃圾回收的?

就像任何其他对象一样。异常被抛出调用堆栈并发生以下两种情况之一:

1) 你捕获它,它被分配给 catch 块中的一个变量:

catch (Exception e) {

e 现在拥有对异常的唯一引用。当不再存在对它的引用时(即它超出了 catch 块底部的范围,或者您传递给它的对象被收集等),它将被收集。

2) 你没有抓住它,它到达了当前线程的调用堆栈的顶部。此时异常超出范围,因此将被收集,并且线程当然会停止。

** 当我说“将被收集”时完全迂腐,我的意思是最终因为当 Java 中的对象不再引用它时,它是 符合条件的收集,GC 处理它。

【讨论】:

    【解决方案2】:

    Java 异常是对象,因此任何其他对象的大小取决于它的结构,如果您创建了自定义异常,您可以(例如)存储完整的二进制文件其他对象,直到您有空闲内存。 您可以为应用程序设置初始空间和最大空间。 可用空间动态变化,现在有 GC 问题。 Java 异常是对象,因此任何其他对象的垃圾回收都会使用您的环境中的规则。

    有关异常的快速参考http://docs.oracle.com/javase/tutorial/essential/exceptions/

    这是一篇关于垃圾回收的文章,其中关键概念是

    Java 中的垃圾回收总结

    1) Java Heap 被分成三代进行垃圾回收。这些是年轻代、终身或老年代和 Perm 区域。

    2) 新对象被创建到年轻代,然后移动到老年代。

    3) 在Heap的Perm区域创建字符串池,垃圾收集可以在perm空间进行,但依赖于JVM到JVM。

    4) Minor 垃圾收集用于将对象从 Eden 空间移动到 Survivor 1 和 Survivor 2 空间,Major 收集用于将对象从年轻代移动到 Tenured 代。

    5) 每当发生重大垃圾回收时,应用程序线程在此期间停止,这将降低应用程序的性能和吞吐量。

    6) 在 java 6 的垃圾收集中应用了很少的性能改进,我们通常使用 JRE 1.6.20 来运行我们的应用程序。

    7) JVM 命令行选项 -Xmx 和 -Xms 用于设置 Java Heap 的起始大小和最大大小。根据我的经验,此参数的理想比例是 1:1 或 1:1.5,例如,您可以将 –Xmx 和 –Xms 都设置为 1GB 或 –Xms 1.2 GB 和 1.8 GB。

    8) 在 Java 中没有手动进行垃圾收集的方法。

    阅读更多:http://javarevisited.blogspot.it/2011/04/garbage-collection-in-java.html

    如果你使用 java 7,一个关于 GC 的有趣问题是这样的

    Java 7 (JDK 7) garbage collection and documentation on G1

    如果您只需要查看状态 bat,如果您需要调整您需要使用 GC 算法结束内存的应用程序的配置,则其他建议很有用。

    【讨论】:

      【解决方案3】:

      我想知道为什么没有人提到创建异常时发生的第一件事是填充了堆栈跟踪:

       public Throwable() {
          fillInStackTrace();
       }
      

      如果您创建自己的 Exception 类并重写 fillInStackTrace() 方法而不执行任何操作,那么您的 Exception 将成为一个简单的 Java 对象,并将占用与其他对象(具有相同字段/值)一样多的内存。但是你当然会失去最宝贵的东西:堆栈跟踪。综上所述,Exception对象占用的内存大部分是由于存储堆栈跟踪(它以内部格式存储,然后在调用getStackTrace()方法时转换为StackTraceElement[])。所以堆栈跟踪越大,异常占用的内存就越多。

      public class LightWeightException extends RuntimeException {
      
          public LightWeightException(String message) {
              super(message);
          }
      
          @Override
          public synchronized Throwable fillInStackTrace() {
              return this;
          }
      }
      

      【讨论】:

        【解决方案4】:

        这很容易自己找出来。启动 jvisualvm 并附加到您要分析的应用程序。 切换到内存选项卡并过滤您要查找的异常。

        这应该让您清楚地了解异常对象使用了多少字节 - 以及这与您的总堆大小有何关系 - 以及它们被收集的程度和频率。

        【讨论】:

          【解决方案5】:

          使用Java Mission Control 进行检查。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-07-03
            • 2013-05-19
            • 2011-07-16
            • 2010-12-21
            • 1970-01-01
            • 2010-09-18
            • 2020-11-01
            • 1970-01-01
            相关资源
            最近更新 更多