如何找到Java中的对象的所有引用?(How to find all referrers of an

2019-10-17 08:51发布

我们有内存泄漏问题,我们不知道是什么/在其中创建某个类的实例太多/所参考。 这发生在生产重负载下,我们无法获得堆转储(以堆转储挂起时间过长HA服务器)。 运行时分析也没有因为性能退化的生产现场的选项,客户是一个随机的碰撞,而不是激动监控试图捞取碰撞瞬间时慢快乐。 我们不知道如何开始崩溃(泄漏),它只是发生在某些时候。

有没有办法从应用程序本身获得对象的引荐/分实例在运行?

我看着http://docs.oracle.com/javase/6/docs/jdk/api/jpda/jdi/com/sun/jdi/ObjectReference.html ,它给一个想法,这样的事情是可能的。

任何指针如何preferrably与自定义代码没有堆转储方式实现这一目标? 再现测试环境问题已经尝试过,似乎详尽的野生鹅追逐。 我们现在需要一个强力的方式来查找原因。

Answer 1:

建议你尝试检查你这是造成这种泄漏的代码。 这里有一些教程和关于同一帮助

IBM在Java中处理内存泄漏文章http://www.ibm.com/developerworks/library/j-leaks/

其他一些有用的文章http://www.openlogic.com/wazi/bid/188158/How-to-Fix-Memory-Leaks-in-Java

此外,还有一个Eclipse的内存分析工具

但最值得推荐的解决方案将尝试运行jvisualvm从JVM在同一台机器上的程序正在运行,启用分析。



Answer 2:

我们通过实例化,然后在克隆收集踪迹解决问题..并通过调度和倾销时,它们的内存变低。

我们知道,导致问题,只是需要的地方出生追捕对象类:

@EntityListeners(AbstractDTOJpaEventListener.class)
@MappedSuperclass
public abstract class AbstractDTO implements Storeable, Serializable, Cloneable {
  /** */
  private static final String SHADOWED_CLASS = "Custom";
  /** */
  protected final static boolean DEBUG_CUSTOM_INSTANCES = true;
  /** */
  public static long TARGET_HITRATE_PER_INTERVAL = 400000;
  /** */
  public static long LOGGING_INTERVAL = Times.MILLISECONDS_IN_TEN_SECONDS;
  /** */
  private static long previousLoggingTime;
  /** */
  protected static int hits;
  /** */
  protected static boolean hitting;
  /** */
  protected static int hitsWithinInterval;

  /**
   * @author Martin
   */
  public static class Hi {
    /**
     * 
     */
    private long hitted;
    private final long createdAt;
    private final StackTraceElement[] stackTraceElements;
    private final String threadName;

    /**
     * @param threadName 
     * @param stackTraceElements 
     */
    public Hi(String threadName, StackTraceElement[] stackTraceElements) {
      this.threadName = threadName;
      this.createdAt = System.currentTimeMillis();
      this.stackTraceElements = stackTraceElements;
    }

    /**
     *
     */
    public void hit() {
      hitted++;
    }

    /**
     * @return the hitted
     */
    public long getHitted() {
      return hitted;
    }

    /**
     * @param hitted the hitted to set
     */
    public void setHitted(long hitted) {
      this.hitted = hitted;
    }

    /**
     * @return the createdAt
     */
    public long getCreatedAt() {
      return createdAt;
    }

    /**
     * @return the stackTraceElements
     */
    public StackTraceElement[] getStackTraceElements() {
      return stackTraceElements;
    }

    /**
     * @return the threadName
     */
    public String getThreadName() {
      return threadName;
    }
  }

  /** */
  protected final static Map<String, Hi> INSTANCE_SHADOW = new ConcurrentHashMap<String, Hi>();

  private static final Comparator<? super Entry<String, Hi>> COMPARATOR = new Comparator<Entry<String, Hi>>() {
    @Override
    public int compare(Entry<String, Hi> o1, Entry<String, Hi> o2) {
      if (o1 == o2) {
        return 0;
      }

      return -Utils.compareNullSafe(o1.getValue().getHitted(), o2.getValue().getHitted(), Compare.ARG0_FIRST);
    }
  };

  /**
   * @param <T> 
   * @return T
   * @see java.lang.Object#clone()
   */
  @SuppressWarnings("unchecked")
  public <T extends AbstractDTO> T clone() {
    try {
      return (T) super.clone();
    } catch (CloneNotSupportedException e) {
      throw new RuntimeException(e);
    } finally {
      if (DEBUG_CUSTOM_INSTANCES && getClass().getSimpleName().equals(SHADOWED_CLASS)) {
        shadowInstance();
      }
    }
  }

  /**
   * 
   */
  protected void shadowInstance() {
    if (DEBUG_CUSTOM_INSTANCES) {
      final long currentTimeMillis = System.currentTimeMillis();

      if (TARGET_HITRATE_PER_INTERVAL <= ++hitsWithinInterval) {
        hitting = true;
      }

      if ((TARGET_HITRATE_PER_INTERVAL / 2) <= ++hits) {
        final Thread currentThread = Thread.currentThread();

        final StackTraceElement[] stackTrace = currentThread.getStackTrace();

        final String key = Utils.getPropertyPath(String.valueOf(System.identityHashCode(currentThread)), displayStackLocaktion(stackTrace))
            .intern();

        Hi hi = INSTANCE_SHADOW.get(key);

        if (hi == null) {
          synchronized (key) {
            hi = INSTANCE_SHADOW.get(key);

            if (hi == null) {
              INSTANCE_SHADOW.put(key, hi = new Hi(currentThread.getName(), stackTrace));
            }

          }
        }

        hi.hit();
      }

      {
        if (getLoggingInterval(currentTimeMillis) != getLoggingInterval(previousLoggingTime)) {
          if (hitsWithinInterval < TARGET_HITRATE_PER_INTERVAL) {
            if (hitting) {
              hitting = false;
            } else {
              hits = 0; // Reset measuring on second round, give chance to burtsy hits
            }
          }

          hitsWithinInterval = 0;
          previousLoggingTime = currentTimeMillis;
        }
      }
    }
  }

  /**
   * @param time
   * @return long
   */
  private long getLoggingInterval(long time) {
    return time / LOGGING_INTERVAL;
  }

  /**
   * @return String
   */
  public static String toStringShadows() {
    final ArrayList<Entry<String, Hi>> entries;

    synchronized (INSTANCE_SHADOW) {
      entries = Convert.toMinimumArrayList(INSTANCE_SHADOW.entrySet());
      INSTANCE_SHADOW.clear();
    }

    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(new Timestamp(System.currentTimeMillis()) + " " + SHADOWED_CLASS + " Class instance instantiantion summary:\n");
    stringBuilder.append("hits=" + hits + ", hitting=" + hitting + ", hitsWithinInterval=" + hitsWithinInterval + ", previousLoggingTime=" + new java.sql.Timestamp(previousLoggingTime));

    if (entries.isEmpty()) {
      return stringBuilder.toString();
    }

    Collections.sort(entries, COMPARATOR);

    int index = 0;
    stringBuilder.append("-----------------------------------------------------------------------");

    for (Entry<String, Hi> entry : entries) {
      Utils.append(stringBuilder, entry.getValue().getHitted() + "\t" + entry.getKey(), "\n");
    }

    for (Entry<String, Hi> entry : entries) {
      final Hi hi = entry.getValue();
      final StackTraceElement[] stackTrace = hi.getStackTraceElements();
      final String groupName = entry.getKey();

      final String threadName = hi.getThreadName();

      stringBuilder.append("\n").append(++index).append('\t');
      stringBuilder.append(hi.getHitted()).append("\tpcs\t").append(groupName);
      stringBuilder.append("\t").append(new Timestamp(hi.getCreatedAt()).toString()).append('\t').append(threadName)
          .append('\t').append(Convert.toString(stackTrace));
    }

    return stringBuilder.toString();
  }

  /**
   * @param stackTrace
   * @return String
   */
  private static String displayStackLocaktion(final StackTraceElement[] stackTrace) {
    StackTraceElement firstDistinguishingStackTraceElement = null;

    for (int index = 0; index < stackTrace.length; index++) {
      firstDistinguishingStackTraceElement = stackTrace[index];
      if (!Arrays.asList(UNWANTED_LOCATIONS).contains(firstDistinguishingStackTraceElement.getClassName())) {
        break;
      }
    }

    StackTraceElement lastDistinguishingStackTraceElement = null;

    for (int index = stackTrace.length-1; 0 <= index; index--) {
      lastDistinguishingStackTraceElement = stackTrace[index];
      if (lastDistinguishingStackTraceElement.getClassName().startsWith(OUR_PACKAGE_DOMAIN)) {
        break;
      }
    }

    return Utils.getPropertyPath(displayName(firstDistinguishingStackTraceElement) + "<-"
        + displayName(lastDistinguishingStackTraceElement));
  }

  /**
   * @param firstDistinguishingStackTraceElement
   * @return String
   */
  private static String displayName(StackTraceElement firstDistinguishingStackTraceElement) {
    return Utils.getPropertyPath(firstDistinguishingStackTraceElement.getClassName(), firstDistinguishingStackTraceElement.getMethodName(),
        String.valueOf(firstDistinguishingStackTraceElement.getLineNumber()));
  }
}


文章来源: How to find all referrers of an object in Java?