/** * Recursively registers all return types to be accessible, down to the java.lang.Class. By * calling this function you ensure a) that all returned objects are accessible from JavaScript, * no matter how nested they are and b) memory leaks. * * @param brdge * @param reg * @param start */ private static void registerCallableRecursively( JSONRPCBridge brdge, Collection<Class<?>> reg, Class<?> start, int levelOfRecursion) { if (levelOfRecursion == 0) return; try { Collection<Class<?>> allRelatedClasses = getAllRelatedClasses(start); // = start.getDeclaredClasses(); // Method[] methods = start.getMethods(); // for (Method method : methods) { for (Class<?> returnType : allRelatedClasses) { // Class<?> returnType = method.getReturnType(); if (reg.contains(returnType)) continue; // I think these classes are already serialized by JSON, so don't make them accessible. if (returnType.equals(String.class)) continue; if (returnType.equals(Void.class)) continue; if (returnType.equals(Float.class)) continue; if (returnType.equals(Double.class)) continue; if (returnType.equals(Integer.class)) continue; if (returnType.equals(ArrayList.class)) continue; if (returnType.equals(Array.class)) continue; reg.add(returnType); brdge.registerCallableReference(returnType); registerCallableRecursively(brdge, reg, returnType, levelOfRecursion - 1); } } catch (Exception e1) { e1.printStackTrace(); } }
/** Convert a collection of ConstantSets to the format expected by GenTest.addClassLiterals. */ public static MultiMap<Class<?>, PrimitiveOrStringOrNullDecl> toMap( Collection<ConstantSet> constantSets) { final MultiMap<Class<?>, PrimitiveOrStringOrNullDecl> map = new MultiMap<Class<?>, PrimitiveOrStringOrNullDecl>(); for (ConstantSet cs : constantSets) { Class<?> clazz; try { clazz = Class.forName(cs.classname); } catch (ClassNotFoundException e) { throw new Error("Class " + cs.classname + " not found on the classpath."); } for (Integer x : cs.ints) { map.add(clazz, new PrimitiveOrStringOrNullDecl(int.class, x.intValue())); } for (Long x : cs.longs) { map.add(clazz, new PrimitiveOrStringOrNullDecl(long.class, x.longValue())); } for (Float x : cs.floats) { map.add(clazz, new PrimitiveOrStringOrNullDecl(float.class, x.floatValue())); } for (Double x : cs.doubles) { map.add(clazz, new PrimitiveOrStringOrNullDecl(double.class, x.doubleValue())); } for (String x : cs.strings) { map.add(clazz, new PrimitiveOrStringOrNullDecl(String.class, x)); } for (Class<?> x : cs.classes) { map.add(clazz, new PrimitiveOrStringOrNullDecl(Class.class, x)); } } return map; }
public static void premain(String args, Instrumentation inst) throws Exception { try { String[] agentArgs; if (args == null) agentArgs = new String[] {""}; else agentArgs = args.split(","); if (!agentArgs[0].equals("instrumenting")) jarFileName = agentArgs[0]; BaseClassTransformer rct = null; rct = new BaseClassTransformer(); if (agentArgs[0].equals("instrumenting")) { initVMClasses = new HashSet<String>(); for (Class<?> c : inst.getAllLoadedClasses()) { ((Set<String>) initVMClasses).add(c.getName()); } } if (!agentArgs[0].equals("instrumenting")) { inst.addTransformer(rct); Tracer.setLocals(new CounterThreadLocal()); Tracer.overrideAll(true); for (Class<?> c : inst.getAllLoadedClasses()) { try { if (c.isInterface()) continue; if (c.isArray()) continue; byte[] bytes = rct.getBytes(c.getName()); if (bytes == null) { continue; } inst.redefineClasses(new ClassDefinition[] {new ClassDefinition(c, bytes)}); } catch (Throwable e) { synchronized (System.err) { System.err.println("" + c + " failed..."); e.printStackTrace(); } } } Runtime.getRuntime() .addShutdownHook( new Thread() { public void run() { Tracer.mark(); try { PrintStream ps = new PrintStream("bailout.txt"); ps.println("Bailouts: " + Tracer.getBailoutCount()); ps.close(); } catch (Exception e) { } Tracer.unmark(); } }); if ("true".equals(System.getProperty("bci.observerOn"))) Tracer.overrideAll(false); } } catch (Exception e) { e.printStackTrace(); } }
/** * Returns all related classes * * @param start * @return */ private static Collection<Class<?>> getAllRelatedClasses(Class<?> start) { List<Class<?>> rval = new ArrayList<Class<?>>(); JavaClass lookupClass; // In case the class fails, return empty. try { lookupClass = Repository.lookupClass(start); } catch (ClassNotFoundException e) { e.printStackTrace(); return rval; } ConstantPool constantPool = lookupClass.getConstantPool(); int length = constantPool.getLength(); for (int i = 0; i < length; i++) { Constant constant = constantPool.getConstant(i); if (constant instanceof ConstantClass) { ConstantClass cc = (ConstantClass) constant; ConstantUtf8 constant2 = (ConstantUtf8) constantPool.getConstant(cc.getNameIndex()); // In case a subclass fails, skip, but print warning. try { String toLoad = constant2.getBytes().replace('/', '.'); if (toLoad.contains("[")) continue; Class<?> forName = Class.forName(toLoad); rval.add(forName); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } return rval; }