View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.javaflow.bytecode;
18  
19  import java.io.IOException;
20  import java.io.ObjectInputStream;
21  import java.io.ObjectOutputStream;
22  import java.io.Serializable;
23  import org.apache.commons.javaflow.utils.ReflectionUtils;
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  
27  /**
28   * Stack to store the frame information along the invocation trace.
29   *
30   * @author <a href="mailto:tcurdt@apache.org">Torsten Curdt</a>
31   * @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
32   * @version CVS $Id: Stack.java 480487 2006-11-29 08:54:42Z bayard $
33   */
34  public class Stack implements Serializable {
35  
36      private static final Log log = LogFactory.getLog(Stack.class);
37      private static final long serialVersionUID = 2L;
38      
39      private int[] istack;
40      private float[] fstack;
41      private double[] dstack;
42      private long[] lstack;
43      private Object[] ostack;
44      private Object[] rstack;
45      private int iTop, fTop, dTop, lTop, oTop, rTop;
46      protected Runnable runnable;
47  
48      public Stack(Runnable pRunnable) {
49          istack = new int[10];
50          lstack = new long[5];
51          dstack = new double[5];
52          fstack = new float[5];
53          ostack = new Object[10];
54          rstack = new Object[5];
55          runnable = pRunnable;
56      }
57  
58      public Stack(final Stack pParent) {
59          istack = new int[pParent.istack.length];
60          lstack = new long[pParent.lstack.length];
61          dstack = new double[pParent.dstack.length];
62          fstack = new float[pParent.fstack.length];
63          ostack = new Object[pParent.ostack.length];
64          rstack = new Object[pParent.rstack.length];
65          iTop = pParent.iTop;
66          fTop = pParent.fTop;
67          dTop = pParent.dTop;
68          lTop = pParent.lTop;
69          oTop = pParent.oTop;
70          rTop = pParent.rTop;
71          System.arraycopy(pParent.istack, 0, istack, 0, iTop);
72          System.arraycopy(pParent.fstack, 0, fstack, 0, fTop);
73          System.arraycopy(pParent.dstack, 0, dstack, 0, dTop);
74          System.arraycopy(pParent.lstack, 0, lstack, 0, lTop);
75          System.arraycopy(pParent.ostack, 0, ostack, 0, oTop);
76          System.arraycopy(pParent.rstack, 0, rstack, 0, rTop);
77          runnable = pParent.runnable;
78      }
79  
80      public boolean hasDouble() {
81          return dTop > 0;
82      }
83      
84      public double popDouble() {
85          if (dTop == 0) {
86              throw new EmptyStackException("pop double");
87          }
88          
89          final double d = dstack[--dTop];
90          log.debug("pop double " + d + " " + getStats());
91          return d;
92      }
93  
94      public boolean hasFloat() {
95          return fTop > 0;
96      }
97  
98      public float popFloat() {
99          if (fTop == 0) {
100             throw new EmptyStackException("pop float");
101         }
102         
103         final float f = fstack[--fTop];
104         log.debug("pop float " + f + " " + getStats());
105         return f;
106     }
107 
108     public boolean hasInt() {
109         return iTop > 0;
110     }
111 
112     public int popInt() {
113         if (iTop == 0) {
114             throw new EmptyStackException("pop int");
115         }
116         
117         final int i = istack[--iTop];
118         log.debug("pop int " + i + " " + getStats());
119         return i;
120     }
121 
122     public boolean hasLong() {
123         return lTop > 0;
124     }
125 
126     public long popLong() {
127         if (lTop == 0) {
128             throw new EmptyStackException("pop long");
129         }
130         
131         final long l = lstack[--lTop];
132         log.debug("pop long " + l + " " + getStats());
133         return l;
134     }
135 
136     public boolean hasObject() {
137         return oTop > 0;
138     }
139 
140     public Object popObject() {
141         if (oTop == 0) {
142             throw new EmptyStackException("pop object");
143         }
144         
145         final Object o = ostack[--oTop];
146         ostack[oTop] = null;  // avoid unnecessary reference to object
147 
148         if(log.isDebugEnabled()) {
149             final String clazz = ReflectionUtils.getClassName(o);
150             final String clazzLoader = ReflectionUtils.getClassLoaderName(o);
151 
152             log.debug("pop object "+ clazz + "/" + clazzLoader + " [" + o + "] ");
153         }
154         
155         return o;
156     }
157 
158     public boolean hasReference() {
159         return rTop > 0;
160     }
161 
162     public Object popReference() {
163         if (rTop == 0) {
164             throw new EmptyStackException("pop reference");
165         }
166         
167         final Object o = rstack[--rTop];
168         rstack[rTop] = null;  // avoid unnecessary reference to object
169 
170         if(log.isDebugEnabled()) {
171             final String clazz = ReflectionUtils.getClassName(o);
172             final String clazzLoader = ReflectionUtils.getClassLoaderName(o);
173 
174             log.debug("pop reference "+ clazz + "/" + clazzLoader + " [" + o + "] " + getStats());
175         }
176         
177         return o;
178     }
179 
180     public void pushDouble(double d) {
181         log.debug("push double " + d + " " + getStats());
182 
183         if (dTop == dstack.length) {
184             double[] hlp = new double[Math.max(8,dstack.length*2)];
185             System.arraycopy(dstack, 0, hlp, 0, dstack.length);
186             dstack = hlp;
187         }
188         dstack[dTop++] = d;
189     }
190 
191     public void pushFloat(float f) {
192         log.debug("push float " + f + " " + getStats());
193         
194         if (fTop == fstack.length) {
195             float[] hlp = new float[Math.max(8,fstack.length*2)];
196             System.arraycopy(fstack, 0, hlp, 0, fstack.length);
197             fstack = hlp;
198         }
199         fstack[fTop++] = f;
200     }
201 
202     public void pushInt(int i) {
203         log.debug("push int " + i + " " + getStats());
204 
205         if (iTop == istack.length) {
206             int[] hlp = new int[Math.max(8,istack.length*2)];
207             System.arraycopy(istack, 0, hlp, 0, istack.length);
208             istack = hlp;
209         }
210         istack[iTop++] = i;
211     }
212 
213     public void pushLong(long l) {
214         log.debug("push long " + l + " " + getStats());
215         
216         if (lTop == lstack.length) {
217             long[] hlp = new long[Math.max(8,lstack.length*2)];
218             System.arraycopy(lstack, 0, hlp, 0, lstack.length);
219             lstack = hlp;
220         }
221         lstack[lTop++] = l;
222     }
223 
224     public void pushObject(Object o) {
225 
226         if (log.isDebugEnabled()) {
227             final String clazz = ReflectionUtils.getClassName(o);
228             final String clazzLoader = ReflectionUtils.getClassLoaderName(o);            
229             log.debug("push object " + clazz + "/" + clazzLoader + " [" + o + "] " + getStats());
230         }
231         
232         if (oTop == ostack.length) {
233             Object[] hlp = new Object[Math.max(8,ostack.length*2)];
234             System.arraycopy(ostack, 0, hlp, 0, ostack.length);
235             ostack = hlp;
236         }
237         ostack[oTop++] = o;
238     }
239 
240     public void pushReference(Object o) {
241 
242         if (log.isDebugEnabled()) {
243             final String clazz = ReflectionUtils.getClassName(o);
244             final String clazzLoader = ReflectionUtils.getClassLoaderName(o);
245     
246             log.debug("push reference " + clazz + "/" + clazzLoader + " [" + o + "] " + getStats());
247         }
248         
249         if (rTop == rstack.length) {
250             Object[] hlp = new Object[Math.max(8,rstack.length*2)];
251             System.arraycopy(rstack, 0, hlp, 0, rstack.length);
252             rstack = hlp;
253         }
254         rstack[rTop++] = o;
255     }
256 
257     public boolean isSerializable() {
258         for (int i = 0; i < rTop; i++) {
259             final Object r = rstack[i];
260             if (!(r instanceof Serializable)) {
261                 return false;
262             }
263         }
264         for (int i = 0; i < oTop; i++) {
265             final Object o = ostack[i];
266             if (!(o instanceof Serializable)) {
267                 return false;
268             }
269         }
270         return true;
271     }
272 
273     public boolean isEmpty() {
274         return iTop==0 && lTop==0 && dTop==0 && fTop==0 && oTop==0 && rTop==0;
275     }
276 
277     private String getStats() {
278         final StringBuffer sb = new StringBuffer();
279         sb.append("i[").append(iTop).append("],");
280         sb.append("l[").append(lTop).append("],");
281         sb.append("d[").append(dTop).append("],");
282         sb.append("f[").append(fTop).append("],");
283         sb.append("o[").append(oTop).append("],");
284         sb.append("r[").append(rTop).append("]");
285         return sb.toString();
286     }
287 
288     private String getContent() {
289         final StringBuffer sb = new StringBuffer();
290         sb.append("i[").append(iTop).append("]\n");
291         sb.append("l[").append(lTop).append("]\n");
292         sb.append("d[").append(dTop).append("]\n");
293         sb.append("f[").append(fTop).append("]\n");
294         sb.append("o[").append(oTop).append("]\n");
295         for(int i=0; i<oTop;i++) {
296             sb.append(' ').append(i).append(": ");
297             sb.append(ReflectionUtils.getClassName(ostack[i])).append('/').append(ReflectionUtils.getClassLoaderName(ostack[i]));
298             sb.append('\n');
299         }
300         sb.append("r[").append(rTop).append("]\n");
301         for(int i=0; i<rTop;i++) {
302             sb.append(' ').append(i).append(": ");
303             sb.append(ReflectionUtils.getClassName(rstack[i])).append('/').append(ReflectionUtils.getClassLoaderName(rstack[i]));
304             sb.append('\n');
305         }
306         
307         return sb.toString();
308     }
309     
310     public String toString() {
311         return getContent();
312     }
313 
314 
315     private void writeObject(ObjectOutputStream s) throws IOException {
316         s.writeInt(iTop);
317         for( int i=0; i<iTop; i++ ) {
318             s.writeInt(istack[i]);
319         }
320 
321         s.writeInt(lTop);
322         for( int i=0; i<lTop; i++ ) {
323             s.writeLong(lstack[i]);
324         }
325 
326         s.writeInt(dTop);
327         for( int i=0; i<dTop; i++ ) {
328             s.writeDouble(dstack[i]);
329         }
330 
331         s.writeInt(fTop);
332         for( int i=0; i<fTop; i++ ) {
333             s.writeDouble(fstack[i]);
334         }
335 
336         s.writeInt(oTop);
337         for( int i=0; i<oTop; i++ ) {
338             s.writeObject(ostack[i]);
339         }
340 
341         s.writeInt(rTop);
342         for( int i=0; i<rTop; i++ ) {
343             s.writeObject(rstack[i]);
344         }
345 
346         s.writeObject(runnable);
347     }
348 
349     private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
350         iTop = s.readInt();
351         istack = new int[iTop];
352         for( int i=0; i<iTop; i++ ) {
353             istack[i] = s.readInt();
354         }
355 
356         lTop = s.readInt();
357         lstack = new long[lTop];
358         for( int i=0; i<lTop; i++ ) {
359             lstack[i] = s.readLong();
360         }
361 
362         dTop = s.readInt();
363         dstack = new double[dTop];
364         for( int i=0; i<dTop; i++ ) {
365             dstack[i] = s.readDouble();
366         }
367 
368         fTop = s.readInt();
369         fstack = new float[fTop];
370         for( int i=0; i<fTop; i++ ) {
371             fstack[i] = s.readFloat();
372         }
373 
374         oTop = s.readInt();
375         ostack = new Object[oTop];
376         for( int i=0; i<oTop; i++ ) {
377             ostack[i] = s.readObject();
378         }
379 
380         rTop = s.readInt();
381         rstack = new Object[rTop];
382         for( int i=0; i<rTop; i++ ) {
383             rstack[i] = s.readObject();
384         }
385 
386         runnable = (Runnable)s.readObject();
387     }
388 
389 }