All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.lib.javassist.bytecode.StackMapTable Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License.  Alternatively, the contents of this file may be used under
 * the terms of the GNU Lesser General Public License Version 2.1 or later,
 * or the Apache License Version 2.0.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 */

package com.feilong.lib.javassist.bytecode;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

import com.feilong.lib.javassist.CannotCompileException;

/**
 * stack_map attribute.
 *
 * 

* This is an entry in the attributes table of a Code attribute. * It was introduced by J2SE 6 for the verification by * typechecking. * * @see StackMap * @since 3.4 */ public class StackMapTable extends AttributeInfo{ /** * The name of this attribute "StackMapTable". */ public static final String tag = "StackMapTable"; /** * Constructs a stack_map attribute. */ StackMapTable(ConstPool cp, byte[] newInfo){ super(cp, tag, newInfo); } StackMapTable(ConstPool cp, int name_id, DataInputStream in) throws IOException{ super(cp, name_id, in); } /** * Makes a copy. * * @exception RuntimeCopyException * if a BadBytecode * exception is thrown while copying, * it is converted into * RuntimeCopyException. * */ @Override public AttributeInfo copy(ConstPool newCp,Map classnames) throws RuntimeCopyException{ try{ return new StackMapTable(newCp, new Copier(this.constPool, info, newCp, classnames).doit()); }catch (BadBytecode e){ throw new RuntimeCopyException("bad bytecode. fatal?"); } } /** * An exception that may be thrown by copy() * in StackMapTable. */ public static class RuntimeCopyException extends RuntimeException{ /** default serialVersionUID */ private static final long serialVersionUID = 1L; /** * Constructs an exception. */ public RuntimeCopyException(String s){ super(s); } } @Override void write(DataOutputStream out) throws IOException{ super.write(out); } /** * Top_variable_info.tag. */ public static final int TOP = 0; /** * Integer_variable_info.tag. */ public static final int INTEGER = 1; /** * Float_variable_info.tag. */ public static final int FLOAT = 2; /** * Double_variable_info.tag. */ public static final int DOUBLE = 3; /** * Long_variable_info.tag. */ public static final int LONG = 4; /** * Null_variable_info.tag. */ public static final int NULL = 5; /** * UninitializedThis_variable_info.tag. */ public static final int THIS = 6; /** * Object_variable_info.tag. */ public static final int OBJECT = 7; /** * Uninitialized_variable_info.tag. */ public static final int UNINIT = 8; /** * A code walker for a StackMapTable attribute. */ public static class Walker{ byte[] info; int numOfEntries; /** * Constructs a walker. * * @param smt * the StackMapTable that this walker * walks around. */ public Walker(StackMapTable smt){ this(smt.get()); } /** * Constructs a walker. * * @param data * the info field of the * attribute_info structure. * It can be obtained by get() * in the AttributeInfo class. */ public Walker(byte[] data){ info = data; numOfEntries = ByteArray.readU16bit(data, 0); } /** * Returns the number of the entries. */ public final int size(){ return numOfEntries; } /** * Visits each entry of the stack map frames. */ public void parse() throws BadBytecode{ int n = numOfEntries; int pos = 2; for (int i = 0; i < n; i++){ pos = stackMapFrames(pos, i); } } /** * Invoked when the next entry of the stack map frames is visited. * * @param pos * the position of the frame in the info * field of attribute_info structure. * @param nth * the frame is the N-th * (0, 1st, 2nd, 3rd, 4th, ...) entry. * @return the position of the next frame. */ int stackMapFrames(int pos,int nth) throws BadBytecode{ int type = info[pos] & 0xff; if (type < 64){ sameFrame(pos, type); pos++; }else if (type < 128){ pos = sameLocals(pos, type); }else if (type < 247){ throw new BadBytecode("bad frame_type in StackMapTable"); }else if (type == 247){ pos = sameLocals(pos, type); }else if (type < 251){ int offset = ByteArray.readU16bit(info, pos + 1); chopFrame(pos, offset, 251 - type); pos += 3; }else if (type == 251){ // SAME_FRAME_EXTENDED int offset = ByteArray.readU16bit(info, pos + 1); sameFrame(pos, offset); pos += 3; }else if (type < 255){ pos = appendFrame(pos, type); }else{ pos = fullFrame(pos); } return pos; } /** * Invoked if the visited frame is a same_frame or * a same_frame_extended. * * @param pos * the position of this frame in the info * field of attribute_info structure. * @param offsetDelta */ public void sameFrame(int pos,int offsetDelta) throws BadBytecode{ } private int sameLocals(int pos,int type) throws BadBytecode{ int top = pos; int offset; if (type < 128){ offset = type - 64; }else{ // type == 247 offset = ByteArray.readU16bit(info, pos + 1); pos += 2; } int tag = info[pos + 1] & 0xff; int data = 0; if (tag == OBJECT || tag == UNINIT){ data = ByteArray.readU16bit(info, pos + 2); objectOrUninitialized(tag, data, pos + 2); pos += 2; } sameLocals(top, offset, tag, data); return pos + 2; } /** * Invoked if the visited frame is a same_locals_1_stack_item_frame * or a same_locals_1_stack_item_frame_extended. * * @param pos * the position. * @param offsetDelta * @param stackTag * stack[0].tag. * @param stackData * stack[0].cpool_index * if the tag is OBJECT, * or stack[0].offset * if the tag is UNINIT. */ public void sameLocals(int pos,int offsetDelta,int stackTag,int stackData) throws BadBytecode{ } /** * Invoked if the visited frame is a chop_frame. * * @param pos * the position. * @param offsetDelta * @param k * the k last locals are absent. */ public void chopFrame(int pos,int offsetDelta,int k) throws BadBytecode{ } private int appendFrame(int pos,int type) throws BadBytecode{ int k = type - 251; int offset = ByteArray.readU16bit(info, pos + 1); int[] tags = new int[k]; int[] data = new int[k]; int p = pos + 3; for (int i = 0; i < k; i++){ int tag = info[p] & 0xff; tags[i] = tag; if (tag == OBJECT || tag == UNINIT){ data[i] = ByteArray.readU16bit(info, p + 1); objectOrUninitialized(tag, data[i], p + 1); p += 3; }else{ data[i] = 0; p++; } } appendFrame(pos, offset, tags, data); return p; } /** * Invoked if the visited frame is a append_frame. * * @param pos * the position. * @param offsetDelta * @param tags * locals[i].tag. * @param data * locals[i].cpool_index * or locals[i].offset. */ public void appendFrame(int pos,int offsetDelta,int[] tags,int[] data) throws BadBytecode{ } private int fullFrame(int pos) throws BadBytecode{ int offset = ByteArray.readU16bit(info, pos + 1); int numOfLocals = ByteArray.readU16bit(info, pos + 3); int[] localsTags = new int[numOfLocals]; int[] localsData = new int[numOfLocals]; int p = verifyTypeInfo(pos + 5, numOfLocals, localsTags, localsData); int numOfItems = ByteArray.readU16bit(info, p); int[] itemsTags = new int[numOfItems]; int[] itemsData = new int[numOfItems]; p = verifyTypeInfo(p + 2, numOfItems, itemsTags, itemsData); fullFrame(pos, offset, localsTags, localsData, itemsTags, itemsData); return p; } /** * Invoked if the visited frame is full_frame. * * @param pos * the position. * @param offsetDelta * @param localTags * locals[i].tag * @param localData * locals[i].cpool_index * or locals[i].offset * @param stackTags * stack[i].tag * @param stackData * stack[i].cpool_index * or stack[i].offset */ public void fullFrame(int pos,int offsetDelta,int[] localTags,int[] localData,int[] stackTags,int[] stackData) throws BadBytecode{ } private int verifyTypeInfo(int pos,int n,int[] tags,int[] data){ for (int i = 0; i < n; i++){ int tag = info[pos++] & 0xff; tags[i] = tag; if (tag == OBJECT || tag == UNINIT){ data[i] = ByteArray.readU16bit(info, pos); objectOrUninitialized(tag, data[i], pos); pos += 2; } } return pos; } /** * Invoked if Object_variable_info * or Uninitialized_variable_info is visited. * * @param tag * OBJECT or UNINIT. * @param data * the value of cpool_index or offset. * @param pos * the position of cpool_index or offset. */ public void objectOrUninitialized(int tag,int data,int pos){ } } static class SimpleCopy extends Walker{ private Writer writer; public SimpleCopy(byte[] data){ super(data); writer = new Writer(data.length); } public byte[] doit() throws BadBytecode{ parse(); return writer.toByteArray(); } @Override public void sameFrame(int pos,int offsetDelta){ writer.sameFrame(offsetDelta); } @Override public void sameLocals(int pos,int offsetDelta,int stackTag,int stackData){ writer.sameLocals(offsetDelta, stackTag, copyData(stackTag, stackData)); } @Override public void chopFrame(int pos,int offsetDelta,int k){ writer.chopFrame(offsetDelta, k); } @Override public void appendFrame(int pos,int offsetDelta,int[] tags,int[] data){ writer.appendFrame(offsetDelta, tags, copyData(tags, data)); } @Override public void fullFrame(int pos,int offsetDelta,int[] localTags,int[] localData,int[] stackTags,int[] stackData){ writer.fullFrame(offsetDelta, localTags, copyData(localTags, localData), stackTags, copyData(stackTags, stackData)); } protected int copyData(int tag,int data){ return data; } protected int[] copyData(int[] tags,int[] data){ return data; } } static class Copier extends SimpleCopy{ private ConstPool srcPool, destPool; private Map classnames; public Copier(ConstPool src, byte[] data, ConstPool dest, Map names){ super(data); srcPool = src; destPool = dest; classnames = names; } @Override protected int copyData(int tag,int data){ if (tag == OBJECT){ return srcPool.copy(data, destPool, classnames); } return data; } @Override protected int[] copyData(int[] tags,int[] data){ int[] newData = new int[data.length]; for (int i = 0; i < data.length; i++){ if (tags[i] == OBJECT){ newData[i] = srcPool.copy(data[i], destPool, classnames); }else{ newData[i] = data[i]; } } return newData; } } /** * Updates this stack map table when a new local variable is inserted * for a new parameter. * * @param index * the index of the added local variable. * @param tag * the type tag of that local variable. * @param classInfo * the index of the CONSTANT_Class_info structure * in a constant pool table. This should be zero unless the tag * is ITEM_Object. * * @see com.feilong.lib.javassist.CtBehavior#addParameter(com.feilong.lib.javassist.CtClass) * @see #typeTagOf(char) * @see ConstPool */ public void insertLocal(int index,int tag,int classInfo) throws BadBytecode{ byte[] data = new InsertLocal(this.get(), index, tag, classInfo).doit(); this.set(data); } /** * Returns the tag of the type specified by the * descriptor. This method returns INTEGER * unless the descriptor is either D (double), F (float), * J (long), L (class type), or [ (array). * * @param descriptor * the type descriptor. * @see Descriptor */ public static int typeTagOf(char descriptor){ switch (descriptor) { case 'D': return DOUBLE; case 'F': return FLOAT; case 'J': return LONG; case 'L': case '[': return OBJECT; // case 'V' : default: return INTEGER; } } /* * This implementation assumes that a local variable initially * holding a parameter value is never changed to be a different * type. * */ static class InsertLocal extends SimpleCopy{ private int varIndex; private int varTag, varData; public InsertLocal(byte[] data, int varIndex, int varTag, int varData){ super(data); this.varIndex = varIndex; this.varTag = varTag; this.varData = varData; } @Override public void fullFrame(int pos,int offsetDelta,int[] localTags,int[] localData,int[] stackTags,int[] stackData){ int len = localTags.length; if (len < varIndex){ super.fullFrame(pos, offsetDelta, localTags, localData, stackTags, stackData); return; } int typeSize = (varTag == LONG || varTag == DOUBLE) ? 2 : 1; int[] localTags2 = new int[len + typeSize]; int[] localData2 = new int[len + typeSize]; int index = varIndex; int j = 0; for (int i = 0; i < len; i++){ if (j == index){ j += typeSize; } localTags2[j] = localTags[i]; localData2[j++] = localData[i]; } localTags2[index] = varTag; localData2[index] = varData; if (typeSize > 1){ localTags2[index + 1] = TOP; localData2[index + 1] = 0; } super.fullFrame(pos, offsetDelta, localTags2, localData2, stackTags, stackData); } } /** * A writer of stack map tables. */ public static class Writer{ ByteArrayOutputStream output; int numOfEntries; /** * Constructs a writer. * * @param size * the initial buffer size. */ public Writer(int size){ output = new ByteArrayOutputStream(size); numOfEntries = 0; output.write(0); // u2 number_of_entries output.write(0); } /** * Returns the stack map table written out. */ public byte[] toByteArray(){ byte[] b = output.toByteArray(); ByteArray.write16bit(numOfEntries, b, 0); return b; } /** * Constructs and a return a stack map table containing * the written stack map entries. * * @param cp * the constant pool used to write * the stack map entries. */ public StackMapTable toStackMapTable(ConstPool cp){ return new StackMapTable(cp, toByteArray()); } /** * Writes a same_frame or a same_frame_extended. */ public void sameFrame(int offsetDelta){ numOfEntries++; if (offsetDelta < 64){ output.write(offsetDelta); }else{ output.write(251); // SAME_FRAME_EXTENDED write16(offsetDelta); } } /** * Writes a same_locals_1_stack_item * or a same_locals_1_stack_item_extended. * * @param tag * stack[0].tag. * @param data * stack[0].cpool_index * if the tag is OBJECT, * or stack[0].offset * if the tag is UNINIT. * Otherwise, this parameter is not used. */ public void sameLocals(int offsetDelta,int tag,int data){ numOfEntries++; if (offsetDelta < 64){ output.write(offsetDelta + 64); }else{ output.write(247); // SAME_LOCALS_1_STACK_ITEM_EXTENDED write16(offsetDelta); } writeTypeInfo(tag, data); } /** * Writes a chop_frame. * * @param k * the number of absent locals. 1, 2, or 3. */ public void chopFrame(int offsetDelta,int k){ numOfEntries++; output.write(251 - k); write16(offsetDelta); } /** * Writes a append_frame. The number of the appended * locals is specified by the length of tags. * * @param tags * locals[].tag. * The length of this array must be * either 1, 2, or 3. * @param data * locals[].cpool_index * if the tag is OBJECT, * or locals[].offset * if the tag is UNINIT. * Otherwise, this parameter is not used. */ public void appendFrame(int offsetDelta,int[] tags,int[] data){ numOfEntries++; int k = tags.length; // k is 1, 2, or 3 output.write(k + 251); write16(offsetDelta); for (int i = 0; i < k; i++){ writeTypeInfo(tags[i], data[i]); } } /** * Writes a full_frame. * number_of_locals and number_of_stack_items * are specified by the the length of localTags and * stackTags. * * @param localTags * locals[].tag. * @param localData * locals[].cpool_index * if the tag is OBJECT, * or locals[].offset * if the tag is UNINIT. * Otherwise, this parameter is not used. * @param stackTags * stack[].tag. * @param stackData * stack[].cpool_index * if the tag is OBJECT, * or stack[].offset * if the tag is UNINIT. * Otherwise, this parameter is not used. */ public void fullFrame(int offsetDelta,int[] localTags,int[] localData,int[] stackTags,int[] stackData){ numOfEntries++; output.write(255); // FULL_FRAME write16(offsetDelta); int n = localTags.length; write16(n); for (int i = 0; i < n; i++){ writeTypeInfo(localTags[i], localData[i]); } n = stackTags.length; write16(n); for (int i = 0; i < n; i++){ writeTypeInfo(stackTags[i], stackData[i]); } } private void writeTypeInfo(int tag,int data){ output.write(tag); if (tag == OBJECT || tag == UNINIT){ write16(data); } } private void write16(int value){ output.write((value >>> 8) & 0xff); output.write(value & 0xff); } } /** * Prints the stack table map. */ public void println(PrintWriter w){ Printer.print(this, w); } /** * Prints the stack table map. * * @param ps * a print stream such as System.out. */ public void println(java.io.PrintStream ps){ Printer.print(this, new java.io.PrintWriter(ps, true)); } static class Printer extends Walker{ private PrintWriter writer; private int offset; /** * Prints the stack table map. */ public static void print(StackMapTable smt,PrintWriter writer){ try{ new Printer(smt.get(), writer).parse(); }catch (BadBytecode e){ writer.println(e.getMessage()); } } Printer(byte[] data, PrintWriter pw){ super(data); writer = pw; offset = -1; } @Override public void sameFrame(int pos,int offsetDelta){ offset += offsetDelta + 1; writer.println(offset + " same frame: " + offsetDelta); } @Override public void sameLocals(int pos,int offsetDelta,int stackTag,int stackData){ offset += offsetDelta + 1; writer.println(offset + " same locals: " + offsetDelta); printTypeInfo(stackTag, stackData); } @Override public void chopFrame(int pos,int offsetDelta,int k){ offset += offsetDelta + 1; writer.println(offset + " chop frame: " + offsetDelta + ", " + k + " last locals"); } @Override public void appendFrame(int pos,int offsetDelta,int[] tags,int[] data){ offset += offsetDelta + 1; writer.println(offset + " append frame: " + offsetDelta); for (int i = 0; i < tags.length; i++){ printTypeInfo(tags[i], data[i]); } } @Override public void fullFrame(int pos,int offsetDelta,int[] localTags,int[] localData,int[] stackTags,int[] stackData){ offset += offsetDelta + 1; writer.println(offset + " full frame: " + offsetDelta); writer.println("[locals]"); for (int i = 0; i < localTags.length; i++){ printTypeInfo(localTags[i], localData[i]); } writer.println("[stack]"); for (int i = 0; i < stackTags.length; i++){ printTypeInfo(stackTags[i], stackData[i]); } } private void printTypeInfo(int tag,int data){ String msg = null; switch (tag) { case TOP: msg = "top"; break; case INTEGER: msg = "integer"; break; case FLOAT: msg = "float"; break; case DOUBLE: msg = "double"; break; case LONG: msg = "long"; break; case NULL: msg = "null"; break; case THIS: msg = "this"; break; case OBJECT: msg = "object (cpool_index " + data + ")"; break; case UNINIT: msg = "uninitialized (offset " + data + ")"; break; } writer.print(" "); writer.println(msg); } } void shiftPc(int where,int gapSize,boolean exclusive) throws BadBytecode{ new OffsetShifter(this, where, gapSize).parse(); new Shifter(this, where, gapSize, exclusive).doit(); } static class OffsetShifter extends Walker{ int where, gap; public OffsetShifter(StackMapTable smt, int where, int gap){ super(smt); this.where = where; this.gap = gap; } @Override public void objectOrUninitialized(int tag,int data,int pos){ if (tag == UNINIT){ if (where <= data){ ByteArray.write16bit(data + gap, info, pos); } } } } static class Shifter extends Walker{ private StackMapTable stackMap; int where, gap; int position; byte[] updatedInfo; boolean exclusive; public Shifter(StackMapTable smt, int where, int gap, boolean exclusive){ super(smt); stackMap = smt; this.where = where; this.gap = gap; this.position = 0; this.updatedInfo = null; this.exclusive = exclusive; } public void doit() throws BadBytecode{ parse(); if (updatedInfo != null){ stackMap.set(updatedInfo); } } @Override public void sameFrame(int pos,int offsetDelta){ update(pos, offsetDelta, 0, 251); } @Override public void sameLocals(int pos,int offsetDelta,int stackTag,int stackData){ update(pos, offsetDelta, 64, 247); } void update(int pos,int offsetDelta,int base,int entry){ int oldPos = position; position = oldPos + offsetDelta + (oldPos == 0 ? 0 : 1); boolean match; if (exclusive){ match = oldPos < where && where <= position; }else{ match = oldPos <= where && where < position; } if (match){ int newDelta = offsetDelta + gap; position += gap; if (newDelta < 64){ info[pos] = (byte) (newDelta + base); }else if (offsetDelta < 64){ byte[] newinfo = insertGap(info, pos, 2); newinfo[pos] = (byte) entry; ByteArray.write16bit(newDelta, newinfo, pos + 1); updatedInfo = newinfo; }else{ ByteArray.write16bit(newDelta, info, pos + 1); } } } static byte[] insertGap(byte[] info,int where,int gap){ int len = info.length; byte[] newinfo = new byte[len + gap]; for (int i = 0; i < len; i++){ newinfo[i + (i < where ? 0 : gap)] = info[i]; } return newinfo; } @Override public void chopFrame(int pos,int offsetDelta,int k){ update(pos, offsetDelta); } @Override public void appendFrame(int pos,int offsetDelta,int[] tags,int[] data){ update(pos, offsetDelta); } @Override public void fullFrame(int pos,int offsetDelta,int[] localTags,int[] localData,int[] stackTags,int[] stackData){ update(pos, offsetDelta); } void update(int pos,int offsetDelta){ int oldPos = position; position = oldPos + offsetDelta + (oldPos == 0 ? 0 : 1); boolean match; if (exclusive){ match = oldPos < where && where <= position; }else{ match = oldPos <= where && where < position; } if (match){ int newDelta = offsetDelta + gap; ByteArray.write16bit(newDelta, info, pos + 1); position += gap; } } } /** * @see CodeIterator.Switcher#adjustOffsets(int, int) */ void shiftForSwitch(int where,int gapSize) throws BadBytecode{ new SwitchShifter(this, where, gapSize).doit(); } static class SwitchShifter extends Shifter{ SwitchShifter(StackMapTable smt, int where, int gap){ super(smt, where, gap, false); } @Override void update(int pos,int offsetDelta,int base,int entry){ int oldPos = position; position = oldPos + offsetDelta + (oldPos == 0 ? 0 : 1); int newDelta = offsetDelta; if (where == position){ newDelta = offsetDelta - gap; }else if (where == oldPos){ newDelta = offsetDelta + gap; }else{ return; } if (offsetDelta < 64){ if (newDelta < 64){ info[pos] = (byte) (newDelta + base); }else{ byte[] newinfo = insertGap(info, pos, 2); newinfo[pos] = (byte) entry; ByteArray.write16bit(newDelta, newinfo, pos + 1); updatedInfo = newinfo; } }else if (newDelta < 64){ byte[] newinfo = deleteGap(info, pos, 2); newinfo[pos] = (byte) (newDelta + base); updatedInfo = newinfo; }else{ ByteArray.write16bit(newDelta, info, pos + 1); } } static byte[] deleteGap(byte[] info,int where,int gap){ where += gap; int len = info.length; byte[] newinfo = new byte[len - gap]; for (int i = 0; i < len; i++){ newinfo[i - (i < where ? 0 : gap)] = info[i]; } return newinfo; } @Override void update(int pos,int offsetDelta){ int oldPos = position; position = oldPos + offsetDelta + (oldPos == 0 ? 0 : 1); int newDelta = offsetDelta; if (where == position){ newDelta = offsetDelta - gap; }else if (where == oldPos){ newDelta = offsetDelta + gap; }else{ return; } ByteArray.write16bit(newDelta, info, pos + 1); } } /** * Undocumented method. Do not use; internal-use only. * *

* This method is for javassist.convert.TransformNew. * It is called to update the stack map table when * the NEW opcode (and the following DUP) is removed. * * @param where * the position of the removed NEW opcode. */ public void removeNew(int where) throws CannotCompileException{ try{ byte[] data = new NewRemover(this.get(), where).doit(); this.set(data); }catch (BadBytecode e){ throw new CannotCompileException("bad stack map table", e); } } static class NewRemover extends SimpleCopy{ int posOfNew; public NewRemover(byte[] data, int pos){ super(data); posOfNew = pos; } @Override public void sameLocals(int pos,int offsetDelta,int stackTag,int stackData){ if (stackTag == UNINIT && stackData == posOfNew){ super.sameFrame(pos, offsetDelta); }else{ super.sameLocals(pos, offsetDelta, stackTag, stackData); } } @Override public void fullFrame(int pos,int offsetDelta,int[] localTags,int[] localData,int[] stackTags,int[] stackData){ int n = stackTags.length - 1; for (int i = 0; i < n; i++){ if (stackTags[i] == UNINIT && stackData[i] == posOfNew && stackTags[i + 1] == UNINIT && stackData[i + 1] == posOfNew){ n++; int[] stackTags2 = new int[n - 2]; int[] stackData2 = new int[n - 2]; int k = 0; for (int j = 0; j < n; j++){ if (j == i){ j++; }else{ stackTags2[k] = stackTags[j]; stackData2[k++] = stackData[j]; } } stackTags = stackTags2; stackData = stackData2; break; } } super.fullFrame(pos, offsetDelta, localTags, localData, stackTags, stackData); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy