jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java
changeset 34371 cc29db9f73d8
parent 34369 b6df4cc80001
parent 34370 70d1245398ed
child 34372 ccdd9223ab7a
equal deleted inserted replaced
34369:b6df4cc80001 34371:cc29db9f73d8
     1 /*
       
     2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 package java.lang;
       
    26 
       
    27 import jdk.internal.misc.JavaLangInvokeAccess;
       
    28 import jdk.internal.misc.SharedSecrets;
       
    29 
       
    30 import static java.lang.StackWalker.Option.*;
       
    31 import java.lang.StackWalker.StackFrame;
       
    32 import java.util.Optional;
       
    33 import java.util.OptionalInt;
       
    34 
       
    35 class StackFrameInfo implements StackFrame {
       
    36     private final static JavaLangInvokeAccess jlInvokeAccess =
       
    37         SharedSecrets.getJavaLangInvokeAccess();
       
    38 
       
    39     // -XX:+MemberNameInStackFrame will initialize MemberName and all other fields;
       
    40     // otherwise, VM will set the hidden fields (injected by the VM).
       
    41     // -XX:+MemberNameInStackFrame is temporary to enable performance measurement
       
    42     //
       
    43     // Footprint improvement: MemberName::clazz and MemberName::name
       
    44     // can replace StackFrameInfo::declaringClass and StackFrameInfo::methodName
       
    45     // Currently VM sets StackFrameInfo::methodName instead of expanding MemberName::name
       
    46 
       
    47     final StackWalker walker;
       
    48     final Class<?> declaringClass;
       
    49     final Object memberName;
       
    50     final int bci;
       
    51 
       
    52     // methodName, fileName, and lineNumber will be lazily set by the VM
       
    53     // when first requested.
       
    54     private String methodName;
       
    55     private String fileName = null;     // default for unavailable filename
       
    56     private int    lineNumber = -1;     // default for unavailable lineNumber
       
    57 
       
    58     /*
       
    59      * Create StackFrameInfo for StackFrameTraverser and LiveStackFrameTraverser
       
    60      * to use
       
    61      */
       
    62     StackFrameInfo(StackWalker walker) {
       
    63         this.walker = walker;
       
    64         this.declaringClass = null;
       
    65         this.bci = -1;
       
    66         this.memberName = jlInvokeAccess.newMemberName();
       
    67     }
       
    68 
       
    69     @Override
       
    70     public String getClassName() {
       
    71         return declaringClass.getName();
       
    72     }
       
    73 
       
    74     @Override
       
    75     public Class<?> getDeclaringClass() {
       
    76         walker.ensureAccessEnabled(RETAIN_CLASS_REFERENCE);
       
    77         return declaringClass;
       
    78     }
       
    79 
       
    80     // Call the VM to set methodName, lineNumber, and fileName
       
    81     private synchronized void ensureMethodInfoInitialized() {
       
    82         if (methodName == null) {
       
    83             setMethodInfo();
       
    84         }
       
    85     }
       
    86 
       
    87     @Override
       
    88     public String getMethodName() {
       
    89         ensureMethodInfoInitialized();
       
    90         return methodName;
       
    91     }
       
    92 
       
    93     @Override
       
    94     public Optional<String> getFileName() {
       
    95         ensureMethodInfoInitialized();
       
    96         return fileName != null ? Optional.of(fileName) : Optional.empty();
       
    97     }
       
    98 
       
    99     @Override
       
   100     public OptionalInt getLineNumber() {
       
   101         ensureMethodInfoInitialized();
       
   102         return lineNumber > 0 ? OptionalInt.of(lineNumber) : OptionalInt.empty();
       
   103     }
       
   104 
       
   105     @Override
       
   106     public boolean isNativeMethod() {
       
   107         ensureMethodInfoInitialized();
       
   108         return lineNumber == -2;
       
   109     }
       
   110 
       
   111     @Override
       
   112     public String toString() {
       
   113         ensureMethodInfoInitialized();
       
   114         // similar format as StackTraceElement::toString
       
   115         if (isNativeMethod()) {
       
   116             return getClassName() + "." + getMethodName() + "(Native Method)";
       
   117         } else {
       
   118             // avoid allocating Optional objects
       
   119             return getClassName() + "." + getMethodName() +
       
   120                 "(" + (fileName != null ? fileName : "Unknown Source") +
       
   121                       (lineNumber > 0 ? ":" + lineNumber : " bci:" + bci) + ")";
       
   122         }
       
   123     }
       
   124 
       
   125     /**
       
   126      * Lazily initialize method name, file name, line number
       
   127      */
       
   128     private native void setMethodInfo();
       
   129 
       
   130     /**
       
   131      * Fill in source file name and line number of the given StackFrame array.
       
   132      */
       
   133     static native void fillInStackFrames(int startIndex,
       
   134                                          Object[] stackframes,
       
   135                                          int fromIndex, int toIndex);
       
   136 }