View Javadoc
1   /*
2    * Copyright (c) 2000, 2001, 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.runtime;
26  
27  import java.util.*;
28  import sun.jvm.hotspot.debugger.*;
29  import sun.jvm.hotspot.runtime.*;
30  import sun.jvm.hotspot.types.*;
31  import sun.jvm.hotspot.utilities.*;
32  
33  /** */
34  public class JNIHandleBlock extends VMObject {
35    private static Field         handlesField;
36    private static CIntegerField topField;
37    private static AddressField  nextField;
38  
39    private static int           blockSizeInOops;
40  
41    static {
42      VM.registerVMInitializedObserver(new Observer() {
43          public void update(Observable o, Object data) {
44            initialize(VM.getVM().getTypeDataBase());
45          }
46        });
47    }
48  
49    private static synchronized void initialize(TypeDataBase db) {
50      Type type = db.lookupType("JNIHandleBlock");
51  
52      handlesField = type.getField("_handles");
53      topField = type.getCIntegerField("_top");
54      nextField = type.getAddressField("_next");
55  
56      blockSizeInOops = db.lookupIntConstant("JNIHandleBlock::block_size_in_oops").intValue();
57    }
58  
59    public JNIHandleBlock(Address addr) {
60      super(addr);
61    }
62  
63    public JNIHandleBlock next() {
64      Address handleAddr = nextField.getValue(addr);
65      if (handleAddr == null) {
66        return null;
67      }
68  
69      /* the next handle block is valid only if the current block is full */
70      if (top() < blockSizeInOops) {
71        return null;
72      }
73      return new JNIHandleBlock(handleAddr);
74    }
75  
76    public int top() {
77      return (int) topField.getValue(addr);
78    }
79  
80    public void oopsDo(AddressVisitor visitor) {
81      // Visit handles in this block
82      for (int i = 0; i < top(); i++) {
83        Address cur = getOopHandleAddress(i);
84        if (cur != null) {
85          visitor.visitAddress(cur);
86        }
87      }
88  
89      // Visit handles in subsequent blocks if necessary
90      JNIHandleBlock n = next();
91      if (n != null) {
92        n.oopsDo(visitor);
93      }
94    }
95  
96    public OopHandle getOopHandle(int x) {
97      Address oopAddr = getOopHandleAddress(x);
98      if (oopAddr != null) {
99        return oopAddr.getOopHandleAt(0);
100     }
101     return null;
102   }
103 
104   /** Debugging routine only. Returns non-null JNIHandleBlock
105       containing the JNI handle or null if this handle block and its
106       successors did not contain it (or if the handle was deleted). */
107   public JNIHandleBlock blockContainingHandle(Address jniHandle) {
108     JNIHandleBlock cur = this;
109     while (cur != null) {
110       if (indexOfHandle(jniHandle) >= 0) {
111         return cur;
112       }
113       cur = cur.next();
114     }
115     return null;
116   }
117 
118   /** Debugging routine: returns the index (0..top() - 1) of the
119       handle in this block, or -1 if the handle was not contained in
120       this block. Does not search successor blocks. */
121   public int indexOfHandle(Address jniHandle) {
122     for (int i = 0; i < top(); i++) {
123       Address addr = getOopHandleAddress(i);
124       if (addr != null) {
125         if (addr.equals(jniHandle)) {
126           return i;
127         }
128       }
129     }
130     return -1;
131   }
132 
133   public String toString() {
134     Address handleBase = addr.addOffsetTo(handlesField.getOffset());
135     Address handleEnd = addr.addOffsetTo(handlesField.getOffset() + top() * VM.getVM().getOopSize());
136     return "JNIHandleBlock [" + handleBase + ", " + handleEnd + ")";
137   }
138 
139   /** Only returns addresses of valid OopHandles */
140   private Address getOopHandleAddress(int x) {
141     if (Assert.ASSERTS_ENABLED) {
142       Assert.that(x < top(), "out of bounds");
143     }
144 
145     Address oopAddr = addr.addOffsetTo(handlesField.getOffset() + x * VM.getVM().getOopSize());
146     OopHandle handle = oopAddr.getOopHandleAt(0);
147     if (VM.getVM().getUniverse().isInReserved(handle) && !VM.getVM().getJNIHandles().isDeletedHandle(handle)) {
148       /* the oop handle is valid only if it is not freed (i.e. reserved in heap) and is not a deleted oop */
149       return oopAddr;
150     } else {
151       return null;
152     }
153   }
154 }