View Javadoc
1   /*
2    * Copyright (c) 2000, 2012, 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.
8    *
9    * This code is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12   * version 2 for more details (a copy is included in the LICENSE file that
13   * accompanied this code).
14   *
15   * You should have received a copy of the GNU General Public License version
16   * 2 along with this work; if not, write to the Free Software Foundation,
17   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18   *
19   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * questions.
22   *
23   */
24  
25  package sun.jvm.hotspot.utilities;
26  
27  import java.io.*;
28  import sun.jvm.hotspot.code.*;
29  import sun.jvm.hotspot.debugger.*;
30  import sun.jvm.hotspot.gc_interface.*;
31  import sun.jvm.hotspot.interpreter.*;
32  import sun.jvm.hotspot.runtime.*;
33  import sun.jvm.hotspot.memory.*;
34  
35  /** This class attempts to describe possible locations of pointers in
36      the VM. */
37  
38  public class PointerLocation {
39    //////////////////////////////////////////////////////////////////
40    //                                                              //
41    // These are package private to simplify the implementation and //
42    // interaction with PointerFinder                               //
43    //                                                              //
44    //////////////////////////////////////////////////////////////////
45  
46    Address addr;
47  
48    CollectedHeap heap;
49    Generation gen;
50  
51    // If UseTLAB was enabled and the pointer was found in a
52    // currently-active TLAB, these will be set
53    boolean inTLAB;
54    JavaThread tlabThread;
55    ThreadLocalAllocBuffer tlab;
56  
57    // Generated code locations
58    boolean inInterpreter;
59    boolean inCodeCache;
60  
61    // FIXME: add other locations like VTableStubs, StubRoutines, maybe
62    // even "on thread x's stack"
63  
64    InterpreterCodelet interpreterCodelet;
65    CodeBlob blob;
66    // FIXME: add more detail about CodeBlob
67    boolean inBlobCode;
68    boolean inBlobData;
69    boolean inBlobOops;
70    boolean inBlobUnknownLocation;
71  
72    boolean inStrongGlobalJNIHandleBlock;
73    boolean inWeakGlobalJNIHandleBlock;
74    boolean inLocalJNIHandleBlock;
75    JNIHandleBlock handleBlock;
76    sun.jvm.hotspot.runtime.Thread handleThread;
77  
78    public PointerLocation(Address addr) {
79      this.addr = addr;
80    }
81  
82    public boolean isInHeap() {
83      return (heap != null || (gen != null));
84    }
85  
86    public boolean isInNewGen() {
87      return ((gen != null) && (gen.level() == 0));
88    }
89  
90    public boolean isInOldGen() {
91      return ((gen != null) && (gen.level() == 1));
92    }
93  
94    public boolean inOtherGen() {
95      return (!isInNewGen() && !isInOldGen());
96    }
97  
98    /** Only valid if isInHeap() */
99    public Generation getGeneration() {
100       return gen;
101   }
102 
103   /** This may be true if isInNewGen is also true */
104   public boolean isInTLAB() {
105     return inTLAB;
106   }
107 
108   /** Only valid if isInTLAB() returns true */
109   public JavaThread getTLABThread() {
110     return tlabThread;
111   }
112 
113   /** Only valid if isInTLAB() returns true */
114   public ThreadLocalAllocBuffer getTLAB() {
115     return tlab;
116   }
117 
118   public boolean isInInterpreter() {
119     return inInterpreter;
120   }
121 
122   /** For now, only valid if isInInterpreter is true */
123   public InterpreterCodelet getInterpreterCodelet() {
124     return interpreterCodelet;
125   }
126 
127   public boolean isInCodeCache() {
128     return inCodeCache;
129   }
130 
131   /** For now, only valid if isInCodeCache is true */
132   public CodeBlob getCodeBlob() {
133     return blob;
134   }
135 
136   public boolean isInBlobCode() {
137     return inBlobCode;
138   }
139 
140   public boolean isInBlobData() {
141     return inBlobData;
142   }
143 
144   public boolean isInBlobOops() {
145     return inBlobOops;
146   }
147 
148   public boolean isInBlobUnknownLocation() {
149     return inBlobUnknownLocation;
150   }
151 
152   public boolean isInStrongGlobalJNIHandleBlock() {
153     return inStrongGlobalJNIHandleBlock;
154   }
155 
156   public boolean isInWeakGlobalJNIHandleBlock() {
157     return inWeakGlobalJNIHandleBlock;
158   }
159 
160   public boolean isInLocalJNIHandleBlock() {
161     return inLocalJNIHandleBlock;
162   }
163 
164   /** Only valid if isInStrongGlobalJNIHandleBlock,
165       isInWeakGlobalJNIHandleBlock, or isInLocalJNIHandleBlock is true */
166   public JNIHandleBlock getJNIHandleBlock() {
167     return handleBlock;
168   }
169 
170   /** Only valid if isInLocalJNIHandleBlock is true */
171   public sun.jvm.hotspot.runtime.Thread getJNIHandleThread() {
172     return handleThread;
173   }
174 
175   public boolean isUnknown() {
176     return (!(isInHeap() || isInInterpreter() || isInCodeCache() ||
177               isInStrongGlobalJNIHandleBlock() || isInWeakGlobalJNIHandleBlock() || isInLocalJNIHandleBlock()));
178   }
179 
180   public String toString() {
181     ByteArrayOutputStream bos = new ByteArrayOutputStream();
182     printOn(new PrintStream(bos));
183     return bos.toString();
184   }
185 
186   public void print() {
187     printOn(System.out);
188   }
189 
190   public void printOn(PrintStream tty) {
191     tty.print("Address ");
192     if (addr == null) {
193       tty.print("0x0");
194     } else {
195       tty.print(addr.toString());
196     }
197     tty.print(": ");
198     if (isInHeap()) {
199       if (isInTLAB()) {
200         tty.print("In thread-local allocation buffer for thread \"" +
201                   getTLABThread().getThreadName() + "\" (");
202         getTLABThread().printThreadIDOn(tty);
203         tty.print(") ");
204         getTLAB().printOn(tty);
205       } else {
206         if (isInNewGen()) {
207           tty.print("In new generation ");
208         } else if (isInOldGen()) {
209           tty.print("In old generation ");
210         } else if (gen != null) {
211           tty.print("In Generation " + getGeneration().level());
212         } else {
213           tty.print("In unknown section of Java heap");
214         }
215         if (getGeneration() != null) {
216           getGeneration().printOn(tty);
217         }
218       }
219     } else if (isInInterpreter()) {
220       tty.println("In interpreter codelet \"" + interpreterCodelet.getDescription() + "\"");
221       interpreterCodelet.printOn(tty);
222     } else if (isInCodeCache()) {
223       CodeBlob b = getCodeBlob();
224       tty.print("In ");
225       if (isInBlobCode()) {
226         tty.print("code");
227       } else if (isInBlobData()) {
228         tty.print("data");
229       } else if (isInBlobOops()) {
230         tty.print("oops");
231       } else {
232         if (Assert.ASSERTS_ENABLED) {
233           Assert.that(isInBlobUnknownLocation(), "Should have known location in CodeBlob");
234         }
235         tty.print("unknown location");
236       }
237       tty.print(" in ");
238       b.printOn(tty);
239 
240       // FIXME: add more detail
241     } else if (isInStrongGlobalJNIHandleBlock() ||
242                isInWeakGlobalJNIHandleBlock() ||
243                isInLocalJNIHandleBlock()) {
244       tty.print("In ");
245       if (isInStrongGlobalJNIHandleBlock()) {
246         tty.print("strong global");
247       } else if (isInWeakGlobalJNIHandleBlock()) {
248         tty.print("weak global");
249       } else {
250         tty.print("thread-local");
251       }
252       tty.print(" JNI handle block (" + handleBlock.top() + " handle slots present)");
253       if (isInLocalJNIHandleBlock()) {
254         if (handleThread.isJavaThread()) {
255           tty.print(" for JavaThread ");
256           ((JavaThread) handleThread).printThreadIDOn(tty);
257         } else {
258           tty.print("for a non-Java Thread");
259         }
260       }
261     } else {
262       // This must be last
263       if (Assert.ASSERTS_ENABLED) {
264         Assert.that(isUnknown(), "Should have unknown location");
265       }
266       tty.print("In unknown location");
267     }
268   }
269 }