Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ hs_err_pid*
/.classpath
/build/*
/bin/
/.gradle/
*.gradle/
/gradle.properties
/site/
Expand Down
1 change: 0 additions & 1 deletion .gradle/2.10/taskArtifacts/cache.properties

This file was deleted.

Binary file removed .gradle/2.10/taskArtifacts/cache.properties.lock
Binary file not shown.
Binary file removed .gradle/2.10/taskArtifacts/fileHashes.bin
Binary file not shown.
Binary file removed .gradle/2.10/taskArtifacts/fileSnapshots.bin
Binary file not shown.
Binary file removed .gradle/2.10/taskArtifacts/outputFileStates.bin
Binary file not shown.
Binary file removed .gradle/2.10/taskArtifacts/taskArtifacts.bin
Binary file not shown.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ Thank you for downloading the Omniscient Debugger (the ODB), the Java debugger t
"backwards in time" so you can examine your program's execution.
Also please visit the project [website](http://omniscientdebugger.github.io/)

# Provenance

The Omniscient Debugger was originally written by Bil Lewis. This repository
continues that work under the LewisODB organization.

This codebase was restarted from the community-maintained
[OmniscientDebugger/LewisOmniscientDebugger](https://github.com/OmniscientDebugger/LewisOmniscientDebugger)
repository, which preserved and modernized the project after the original
distribution. We gratefully acknowledge that work and the contributors whose
history is preserved in Git.

# System Requirements
ODB 1.4 works on code complied for JDK 1.3 and 1.4. ODB 1.5 works on code compiled for JDK 1.5.
I have tested it on 1.6 and it works. Code compiled for Java 7 and up use invokedetatch, which seems to cause problems at the moment. See [Issue](https://github.com/OmniscientDebugger/LewisOmniscientDebugger/issues/1): The Jar's compiled for 1.6 and older do work on the 1.8 JVM.
Expand Down Expand Up @@ -70,7 +81,7 @@ mkdocs build --strict
# Development
Here is how to build and run the debug the debugger step
```
git clone https://github.com/OmniscientDebugger/LewisOmniscientDebugger.git
git clone https://github.com/LewisODB/OmniscientDebugger.git

gradle jar

Expand Down
6 changes: 3 additions & 3 deletions docs/user-manual/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,8 @@ Here is a sample. All of the lines may have duplicate entires (e.g., the DontIns
StartPattern:
StopPattern:
SourceDirectory:
OnlyInstrument: "org.apache"
OnlyInstrument: "fr.emn.info.eaop.cps"
OnlyInstrument: "org.apache."
OnlyInstrument: "fr.emn.info.eaop.cps."
DontInstrument: "recoder.java.declaration.TypeDeclaration"
DontInstrumentMethod: "* toString"
DontInstrumentMethod: "* valueOf"
Expand All @@ -303,7 +303,7 @@ Here is a sample. All of the lines may have duplicate entires (e.g., the DontIns

You may request some objects to include a field value in their print string by setting the user selected field as above. The field choosen must be a primitive and must not change.

The ODB will write out a "`DidntInstrument/OnlyInstrument`" line for every single class loaded. This makes it easier to change the set of classes being instrumented. By default, only the classes in the package of the "main" method are instrumented.
The ODB will write out a "`DidntInstrument/OnlyInstrument`" line for every single class loaded. This makes it easier to change the set of classes being instrumented. By default, only the classes in the package of the "main" method are instrumented. A trailing dot means a package prefix, such as `"java_programs."`; package-only lists let the runtime loader delegate non-matching classes to the parent loader.

## Finding the Source Code

Expand Down
22 changes: 2 additions & 20 deletions src/main/java/com/lambda/Debugger/Debugify.java
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public final class Debugify implements Constants {
NO_ATHROW = false, NO_CATCH = false, NO_INVOKESTATIC = false,
NO_NEW = false, NO_AASTORE = false, NO_PREVIOUS = false,
NO_LOCKS = false, NO_WAITS = false, DONT_REPLACE_VECTOR = false;
static VectorD dontRecord, dontInstrument, instrumentOnlyPackages;
static VectorD dontRecord, dontInstrument;
static CodeExceptionGen[] ceg;
static String classPackageName, className, classNoNumbers;

Expand Down Expand Up @@ -291,7 +291,6 @@ public static void initialize() {
// Read the file for methods not to record
dontInstrument = Defaults.dontInstrument;
// Read the file for methods not to instrument
instrumentOnlyPackages = Defaults.instrumentOnlyPackages;
}

public static JavaClass debugifyClass(JavaClass javaClass1,
Expand Down Expand Up @@ -569,24 +568,7 @@ public static JavaClass publicifyClass(JavaClass javaClass1,
static boolean dontProcessPackage(String cName) {
if (calledFromDebugify)
return false; // If this is a direct request, do it!
int len = instrumentOnlyPackages.size();
if (len == 0)
return false;

for (int i = 0; i < len; i++) {
String iOnly = (String) instrumentOnlyPackages.elementAt(i);
// Debugger.println("only methods: " + cName + "."+ "? startswith "
// + iOnly);
if (iOnly.equals("")) {
int dot = cName.indexOf(".");
if (dot == -1)
return false;
} else if (cName.startsWith(iOnly))
return false;
}
if (!Defaults.didntInstrument.contains(cName))
Defaults.didntInstrument.add(cName);
return true;
return Defaults.instrumentOnlyExcludes(cName, false);
}

static boolean dontProcessMethod(VectorD cmPairs, String mName,
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/com/lambda/Debugger/DebugifyingClassLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ public class DebugifyingClassLoader extends java.lang.ClassLoader {
dontInstrument.add("java.");
dontInstrument.add("sun.");
dontInstrument.add("apple.");
dontInstrument.add("com.apple.");
dontInstrument.add("com.sun.");
dontInstrument.add("jdk.");
dontInstrument.add("javax.");
dontInstrument.add("JAVAX.");
dontInstrument.add("org.apache.bcel");
Expand Down Expand Up @@ -97,8 +100,7 @@ protected Class loadClass(String className, boolean resolve)
if (clazz != null)
return clazz;

if ((!className.startsWith("javax.xml."))
&& (dontInstrument(className) || (!Debugger.INSTRUMENT))) {
if (shouldDelegateToParent(className)) {
clazz = getParent().loadClass(className);
if (Debugger.TRACE_LOADER)
println("loaded via parent: " + getParent() + " " + className);
Expand Down Expand Up @@ -132,6 +134,14 @@ protected Class loadClass(String className, boolean resolve)
return clazz;
}

private boolean shouldDelegateToParent(String className) {
if (className.startsWith("javax.xml."))
return false;

return dontInstrument(className) || (!Debugger.INSTRUMENT)
|| Defaults.instrumentOnlyExcludes(className, true);
}

public static byte[] debugify(String className, byte[] bytes) {
if (!Debugger.INSTRUMENT)
return bytes;
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/com/lambda/Debugger/Defaults.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,35 @@ static private void setStopOutput(String value){ // "Stop recording when the pr
static private void addInstrumentOnly(String value){ // "com.foo"
instrumentOnlyPackages.add(getString(value));
}
static boolean instrumentOnlyExcludes(String cName, boolean packagePrefixesOnly) {
if (packagePrefixesOnly && !instrumentOnlyEntriesArePackagePrefixes())
return false;

int len = instrumentOnlyPackages.size();
if (len == 0)
return false;

for (int i = 0; i < len; i++) {
String iOnly = (String) instrumentOnlyPackages.elementAt(i);
if (iOnly.equals("")) {
if (cName.indexOf(".") == -1)
return false;
} else if (cName.startsWith(iOnly))
return false;
}
if (!didntInstrument.contains(cName))
didntInstrument.add(cName);
return true;
}
static private boolean instrumentOnlyEntriesArePackagePrefixes() {
int len = instrumentOnlyPackages.size();
for (int i = 0; i < len; i++) {
String iOnly = (String) instrumentOnlyPackages.elementAt(i);
if (!(iOnly.equals("") || iOnly.endsWith(".")))
return false;
}
return true;
}
static private void addDidntInstrument(String value){ // "com.foo.UnparentedToo"
didntInstrument.add(getString(value));
}
Expand Down Expand Up @@ -301,6 +330,7 @@ static public void writeDefaults(){
w.write("# SourceDirectory: If sources can't be found normally, look here.\n");
w.write("# OnlyInstrument: Only classes which match this prefix will be instrumented.\n");
w.write("# OnlyInstrument: \"\" means default package only. No entry means everything.\n");
w.write("# OnlyInstrument: Trailing-dot package prefixes let the runtime loader delegate non-matches.\n");
w.write("# UserSelectedField: This instance variable (a final String) will be appended to the display string\n");
w.write("# UserSelectedField: \"com.lambda.Thing name\" -> <Thing_23 John>\n");
w.write("# SpecialFormatter: com.lambda.Debugger.SpecialTimeStampFormatter\n");
Expand Down
77 changes: 77 additions & 0 deletions src/test/java/com/lambda/Debugger/DebugifyingClassLoaderTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.lambda.Debugger;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class DebugifyingClassLoaderTest {
private VectorD originalInstrumentOnlyPackages;
private VectorD originalDidntInstrument;

@Before
public void saveDefaults() {
originalInstrumentOnlyPackages = Defaults.instrumentOnlyPackages;
originalDidntInstrument = Defaults.didntInstrument;
Defaults.instrumentOnlyPackages = new VectorD();
Defaults.didntInstrument = new VectorD();
}

@After
public void restoreDefaults() {
Defaults.instrumentOnlyPackages = originalInstrumentOnlyPackages;
Defaults.didntInstrument = originalDidntInstrument;
}

@Test
public void emptyOnlyInstrumentKeepsLegacyClassloaderBehavior() {
assertFalse(Defaults.instrumentOnlyExcludes("com.apple.laf.AquaLookAndFeel", true));
}

@Test
public void packageOnlyInstrumentDelegatesClassesOutsidePackage() {
Defaults.instrumentOnlyPackages.add("java_programs.");

assertFalse(Defaults.instrumentOnlyExcludes("java_programs.GCDRunner", true));
assertFalse(Defaults.instrumentOnlyExcludes("java_programs.extra.NESTED_PARENS", true));
assertTrue(Defaults.instrumentOnlyExcludes("com.apple.laf.AquaLookAndFeel", true));
assertTrue(Defaults.didntInstrument.contains("com.apple.laf.AquaLookAndFeel"));
}

@Test
public void defaultPackageOnlyInstrumentDelegatesNamedPackages() {
Defaults.instrumentOnlyPackages.add("");

assertFalse(Defaults.instrumentOnlyExcludes("Main", true));
assertTrue(Defaults.instrumentOnlyExcludes("helpers.Main", true));
}

@Test
public void classPrefixOnlyInstrumentKeepsPublicifyBehavior() {
Defaults.instrumentOnlyPackages.add("java_programs.GCD");

assertFalse(Defaults.instrumentOnlyExcludes("java_programs.Helper", true));
assertFalse(Defaults.instrumentOnlyExcludes("other.Helper", true));
assertTrue(Defaults.instrumentOnlyExcludes("other.Helper", false));
}

@Test
public void mixedOnlyInstrumentKeepsPublicifyBehavior() {
Defaults.instrumentOnlyPackages.add("java_programs.");
Defaults.instrumentOnlyPackages.add("other.Specific");

assertFalse(Defaults.instrumentOnlyExcludes("helpers.Main", true));
}

@Test
public void platformVendorClassesLoadThroughParent() throws Exception {
DebugifyingClassLoader loader = new DebugifyingClassLoader();

Class clazz = loader.loadClass("com.sun.java.swing.plaf.motif.MotifLookAndFeel");

assertNotSame(loader, clazz.getClassLoader());
}
}
Loading