private void addGetEnhancementContractVersionMethod() { // public int getEnhancementContractVersion() BCMethod method = _pc.declareMethod(PRE + "GetEnhancementContractVersion", int.class, null); method.makePublic(); Code code = method.getCode(true); code.constant().setValue(ENHANCER_VERSION); code.ireturn(); code.calculateMaxStack(); code.calculateMaxLocals(); }
/** * Add an exception handler to this code block. * * @param tryStart the first instruction of the try {} block * @param tryEnd the last instruction of the try {} block * @param handlerStart the first instruction of the catch {} block * @param catchType the type of exception being caught */ public ExceptionHandler addExceptionHandler(Instruction tryStart, Instruction tryEnd, Instruction handlerStart, Class catchType) { String catchName = null; if (catchType != null) catchName = catchType.getName(); return addExceptionHandler(tryStart, tryEnd, handlerStart, catchName); }
/** * Set the name of the class to load. */ private void setClassName(String name, Class wrapper) { if (_invalid) throw new IllegalStateException(); // remember the position of the code iterator Instruction before = (_code.hasNext()) ? _code.next() : null; _code.before(_ins); _code.next(); if (wrapper != null) _code.getstatic().setField(wrapper, "TYPE", Class.class); else setObject(name); // move to the old position if (before != null) _code.before(before); else _code.afterLast(); _invalid = true; }
/** * Set the exception handlers for this code block. This method is useful * for importing all handlers from another code block. Set to null or * empty array if none. */ public void setExceptionHandlers(ExceptionHandler[] handlers) { clearExceptionHandlers(); if (handlers != null) for (int i = 0; i < handlers.length; i++) addExceptionHandler(handlers[i]); }
/** * Replaces all the instructions in this code block that match the * given template with the given instruction. After this method, * the iterator will be {@link #afterLast}. * * @return the number of substitutions made */ public int replace(Instruction template, Instruction with) { beforeFirst(); int count; for (count = 0; searchForward(template); count++) set(with); return count; }
/** * Throw an exception of the given type. */ protected Instruction throwException(Code code, Class type) { Instruction ins = code.anew().setType(type); code.dup(); code.invokespecial().setMethod(type, "<init>", void.class, null); code.athrow(); return ins; }
code.beforeFirst(); code.invokevirtual().setMethod(PRE + "Serializing", boolean.class, null); int clear = code.getNextLocalsIndex(); code.istore().setLocal(clear); code.aload().setParam(0); code.invokevirtual().setMethod(ObjectOutputStream.class, "defaultWriteObject", void.class, null); code.vreturn(); J2DoPrivHelper.newCodeAction())).vreturn(); JumpInstruction toret; Instruction ret; code.beforeFirst(); while (code.searchForward(tmplate)) { ret = code.previous(); code.iload().setLocal(clear); toret = code.ifeq(); loadManagedInstance(code, false); code.constant().setNull(); code.invokevirtual().setMethod(PRE + "SetDetachedState", void.class, new Class[]{ Object.class }); toret.setTarget(ret); code.next(); // jump over return code.calculateMaxStack();
/** * Enhance constructor to initialize fields */ private void enhanceConstructor(BCClass bc) { BCMethod cons = bc.getDeclaredMethod("<init>", (String[]) null); Code code = cons.getCode(false); code.afterLast(); code.previous(); // private BitSet loaded = new BitSet(); BCField loaded = addBeanField(bc, "loaded", BitSet.class); loaded.setFinal(true); code.aload().setThis(); code.anew().setType(BitSet.class); code.dup(); code.constant().setValue(bc.getFields().length); code.invokespecial().setMethod(BitSet.class, "<init>", void.class, new Class[]{ int.class }); code.putfield().setField(loaded); code.calculateMaxStack(); code.calculateMaxLocals(); }
code.setMaxStack(3); code.setMaxLocals(2); Instruction tryStart = code.aload().setLocal(0); code.invokestatic().setMethod(Class.class, "forName", Class.class, _params); Instruction tryEnd = code.areturn(); Instruction handlerStart = code.astore().setLocal(1); code.anew().setType(NoClassDefFoundError.class); code.dup(); code.aload().setLocal(1); code.invokevirtual().setMethod(Throwable.class, "getMessage", String.class, null); code.invokespecial().setMethod(NoClassDefFoundError.class, "<init>", void.class, _params); code.athrow(); code.addExceptionHandler(tryStart, tryEnd, handlerStart, ClassNotFoundException.class); return method;
/** * Adds a custom readObject method that delegates to the * {@link ObjectInputStream#readObject} method. */ private void modifyReadObjectMethod(BCMethod method, boolean full) { Code code = method.getCode(true); code.beforeFirst(); // if this instance uses synthetic detached state, note that it has // been deserialized if (ClassMetaData.SYNTHETIC.equals(_meta.getDetachedState())) { loadManagedInstance(code, false); code.getstatic().setField(PersistenceCapable.class, "DESERIALIZED", Object.class); code.invokevirtual().setMethod(PRE + "SetDetachedState", void.class, new Class[]{ Object.class }); } if (full) { // in.defaultReadObject (); code.aload().setParam(0); code.invokevirtual().setMethod(ObjectInputStream.class, "defaultReadObject", void.class, null); code.vreturn(); } code.calculateMaxStack(); code.calculateMaxLocals(); }
Instruction first = code.aload().setThis(); code.getfield().setField("objects", Object[].class); code.constant().setValue(objectCount); code.aaload(); code.astore().setLocal(inter); code.aload().setLocal(inter); jumps2.add(code.ifnull()); code.aload().setParam(0); code.invokeinterface().setMethod(OpenJPAStateManager.class, "getLoaded", BitSet.class, null); code.constant().setValue(index); code.invokevirtual().setMethod(BitSet.class, "get", boolean.class, new Class[]{ int.class }); jumps2.add(code.ifne()); code.aload().setParam(0); code.constant().setValue(index); code.aload().setLocal(inter); code.invokeinterface().setMethod(OpenJPAStateManager.class, "setIntermediate", void.class, new Class[]{ int.class, Object.class });
/** * Implement the newInstance method. */ private void addFactoryMethod(BCClass bc) { BCMethod method = bc.declareMethod("newInstance", DynamicStorage.class, null); Code code = method.getCode(true); code.anew().setType(bc); code.dup(); code.invokespecial().setMethod(bc.getName(), "<init>", "void", null); code.areturn(); code.calculateMaxLocals(); code.calculateMaxStack(); }
private void addGetData(BCClass bc) { // return getObjectField(i); BCMethod method = bc.declareMethod("getData", Object.class, new Class[]{ int.class }); Code code = method.getCode(true); code.aload().setThis(); code.iload().setParam(0); code.invokevirtual().setMethod("getObject", Object.class, new Class[]{ int.class }); code.areturn(); code.calculateMaxLocals(); code.calculateMaxStack(); }
/** * Add a writeReplace implementation that serializes to a non-proxy type * unless detached and this is a build-time generated class. */ private void addWriteReplaceMethod(BCClass bc, boolean runtime) { BCMethod m = bc.declareMethod("writeReplace", Object.class, null); m.makeProtected(); m.getExceptions(true).addException(ObjectStreamException.class); Code code = m.getCode(true); code.aload().setThis(); code.constant().setValue(!runtime); code.invokestatic().setMethod(Proxies.class, "writeReplace", Object.class, new Class[] { Proxy.class, boolean.class }); code.areturn(); code.calculateMaxLocals(); code.calculateMaxStack(); }
/** * Adds fields and methods as necessary to load a class constant of * an object type. */ private void setObject(String name) { BCField field = addClassField(name); BCMethod method = addClassLoadMethod(); // copied from the way jikes loads classes _code.getstatic().setField(field); JumpInstruction ifnull = _code.ifnull(); _code.getstatic().setField(field); JumpInstruction go2 = _code.go2(); ifnull.setTarget(_code.constant().setValue(name)); _code.invokestatic().setMethod(method); _code.dup(); _code.putstatic().setField(field); go2.setTarget(_code.nop()); }
/** * Invalidate methods on the interface which are not managed. */ private void invalidateNonBeanMethods(BCClass bc, Class<?> iface, Set<Method> methods) { Method[] meths = (Method[]) AccessController.doPrivileged( J2DoPrivHelper.getDeclaredMethodsAction(iface)); BCMethod meth; Code code; Class<?> type = _repos.getMetaDataFactory().getDefaults(). getUnimplementedExceptionType(); for (int i = 0; i < meths.length; i++) { if (methods.contains(meths[i])) continue; meth = bc.declareMethod(meths[i].getName(), meths[i].getReturnType(), meths[i].getParameterTypes()); meth.makePublic(); code = meth.getCode(true); code.anew().setType(type); code.dup(); code.invokespecial().setMethod(type, "<init>", void.class, null); code.athrow(); code.calculateMaxLocals(); code.calculateMaxStack(); } }
/** * Copy bean properties. Called with the copy object on the stack. Must * return with the copy object on the stack. */ private void copyProperties(Class type, Code code) { int copy = code.getNextLocalsIndex(); code.astore().setLocal(copy); Method[] meths = type.getMethods(); Method getter; int mods; for (int i = 0; i < meths.length; i++) { mods = meths[i].getModifiers(); if (!Modifier.isPublic(mods) || Modifier.isStatic(mods)) continue; if (!startsWith(meths[i].getName(), "set") || meths[i].getParameterTypes().length != 1) continue; getter = findGetter(type, meths[i]); if (getter == null) continue; // copy.setXXX(orig.getXXX()); code.aload().setLocal(copy); code.aload().setParam(0); code.checkcast().setType(type); code.invokevirtual().setMethod(getter); code.invokevirtual().setMethod(meths[i]); } code.aload().setLocal(copy); }
/** * Proxy the given method with one that overrides it by calling into the * given helper. */ private void proxyOverrideMethod(BCClass bc, Method meth, Method helper, Class[] params) { BCMethod m = bc.declareMethod(meth.getName(), meth.getReturnType(), meth.getParameterTypes()); m.makePublic(); Code code = m.getCode(true); code.aload().setThis(); for (int i = 1; i < params.length; i++) code.xload().setParam(i - 1).setType(params[i]); code.invokestatic().setMethod(helper); code.xreturn().setType(meth.getReturnType()); code.calculateMaxStack(); code.calculateMaxLocals(); }
/** * Adds the appropriate store method for the given type and local * index. */ private void storeLocalValue(Code code, int locidx, int typeCode) { switch (typeCode) { case JavaTypes.CHAR: case JavaTypes.BYTE: case JavaTypes.SHORT: case JavaTypes.INT: code.istore().setLocal(locidx); break; case JavaTypes.DOUBLE: code.dstore().setLocal(locidx); break; case JavaTypes.FLOAT: code.fstore().setLocal(locidx); break; case JavaTypes.LONG: code.lstore().setLocal(locidx); break; default: code.astore().setLocal(locidx); break; } }
private void addNotifyAccess(Code code, FieldMetaData fmd) { // PCHelper.accessingField(this, <absolute-index>); code.aload().setThis(); code.constant().setValue(fmd.getIndex()); code.invokestatic().setMethod(RedefinitionHelper.class, "accessingField", void.class, new Class[] { Object.class, int.class }); }