private byte[] tryTransform( byte[] buffer, String name, ClassLoader loader, String key, boolean isInterface, boolean isOverride) { List<RuleScript> ruleScripts; if (isInterface) { ruleScripts = scriptRepository.scriptsForInterfaceName(key); } else { ruleScripts = scriptRepository.scriptsForClassName(key); } byte[] newBuffer = buffer; if (ruleScripts != null) { // if (isVerbose()) { // System.out.println("tryTransform : " + name + " for " + key); // } int counter = 0; for (RuleScript ruleScript : ruleScripts) { try { // we only transform via isOverride rules if isOverride is true // we tarsnform via any matchign rules if isOverride is false if (!isOverride || ruleScript.isOverride()) { // only do the transform if the script has not been deleted synchronized (ruleScript) { if (!ruleScript.isDeleted()) { maybeDumpClassIntermediate(name, newBuffer); newBuffer = transform(ruleScript, loader, name, newBuffer); } } } } catch (Throwable th) { // yeeeurgh I know this looks ugly with no rethrow but it is appropriate // we do not want to pass on any errors or runtime exceptions // if a transform fails then we should still allow the load to continue // with whatever other transforms succeed. we tarce the throwable to // System.err just to ensure it can be seen. System.err.println("Transformer.transform : caught throwable " + th); th.printStackTrace(System.err); } } } return newBuffer; }
private static void resetLambdaClassSequenceNumber() { try { Field counterField = Class.forName("java.lang.invoke.InnerClassLambdaMetafactory").getDeclaredField("counter"); counterField.setAccessible(true); AtomicInteger counter = (AtomicInteger) counterField.get(null); counter.set(0); } catch (Throwable t) { // print to stdout to keep in sync with other log output System.out.println( "WARNING: Failed to start class numbering from one. Don't worry, it's cosmetic, " + "but please file a bug report and tell on which JDK version this happened."); t.printStackTrace(System.out); } }
private static void dumpClass(String fullName, byte[] bytes, boolean intermediate) { // wrap this in a try catch in case the file i/o code generates a runtime exception // this may happen e.g. because of a security restriction try { int dotIdx = fullName.lastIndexOf('.'); String name = (dotIdx < 0 ? fullName : fullName.substring(dotIdx + 1)); String prefix = (dotIdx > 0 ? File.separator + fullName.substring(0, dotIdx) : ""); String dir = getDumpGeneratedClassesDir() + prefix.replace('.', File.separatorChar); if (!ensureDumpDirectory(dir)) { System.out.println( "org.jboss.byteman.agent.Transformer : Cannot dump transformed bytes to directory " + dir + File.separator + prefix); return; } String newname; if (intermediate) { int counter = 0; // add _<n> prefix until we come up with a new name newname = dir + File.separator + name + "_" + counter + ".class"; File file = new File(newname); while (file.exists()) { counter++; newname = dir + File.separator + name + "_" + counter + ".class"; file = new File(newname); } } else { newname = dir + File.separator + name + ".class"; } System.out.println( "org.jboss.byteman.agent.Transformer : Saving transformed bytes to " + newname); try { FileOutputStream fio = new FileOutputStream(newname); fio.write(bytes); fio.close(); } catch (IOException ioe) { System.out.println("Error saving transformed bytes to" + newname); ioe.printStackTrace(System.out); } } catch (Throwable th) { System.out.println( "org.jboss.byteman.agent.Transformer : Error saving transformed bytes for class " + fullName); th.printStackTrace(System.out); } }