Skip to content

Commit

Permalink
Add /debug/loader/cds debug option to framework
Browse files Browse the repository at this point in the history
This adds trace option for the share classes support (CDS)
  • Loading branch information
tjwatson committed May 9, 2024
1 parent 296576b commit bb4e748
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 19 deletions.
2 changes: 2 additions & 0 deletions bundles/org.eclipse.osgi/.options
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ org.eclipse.osgi/debug=false
org.eclipse.osgi/debug/location = false
# Prints out class loading debug information
org.eclipse.osgi/debug/loader=false
# Prints out CDS class loading debug information
org.eclipse.osgi/debug/loader/cds=false
# Prints out event (FrameworkEvent/BundleEvent/ServiceEvent) and listener debug information
org.eclipse.osgi/debug/events=false
# Prints out OSGi service debug information (registration/getting/ungetting etc.)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@

package org.eclipse.osgi.internal.cds;

import com.ibm.oti.shared.SharedClassURLHelper;
import static org.eclipse.osgi.internal.cds.CDSHookConfigurator.print;

import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper;

import com.ibm.oti.shared.SharedClassURLHelper;

/**
* Wraps an actual BundleFile object for purposes of loading classes from the
* shared classes cache.
Expand All @@ -38,14 +43,16 @@ public class CDSBundleFile extends BundleFileWrapper {
private final URL url; // the URL to the content of the real bundle file
private SharedClassURLHelper urlHelper; // the url helper set by the classloader
private boolean primed = false;
private final Debug debug;

/**
* The constructor
*
* @param wrapped the real bundle file
*/
public CDSBundleFile(BundleFile wrapped) {
public CDSBundleFile(BundleFile wrapped, Debug debug) {
super(wrapped);
this.debug = debug;
// get the url to the content of the real bundle file
URL content = null;
try {
Expand All @@ -56,8 +63,8 @@ public CDSBundleFile(BundleFile wrapped) {
this.url = content;
}

public CDSBundleFile(BundleFile bundleFile, SharedClassURLHelper urlHelper) {
this(bundleFile);
public CDSBundleFile(BundleFile bundleFile, Debug debug, SharedClassURLHelper urlHelper) {
this(bundleFile, debug);
this.urlHelper = urlHelper;
}

Expand All @@ -80,7 +87,11 @@ public BundleEntry getEntry(String path) {
}
byte[] classbytes = getClassBytes(path.substring(0, path.length() - classFileExt.length()));
if (classbytes == null) {
return super.getEntry(path);
BundleEntry fromSuper = super.getEntry(path);
if (fromSuper != null) {
print(debug, () -> "Defining class from original bytes: " + url + ' ' + fromSuper.getName()); //$NON-NLS-1$
}
return fromSuper;
}

BundleEntry be = new CDSBundleEntry(path, classbytes, this);
Expand Down Expand Up @@ -141,7 +152,10 @@ void setPrimed(boolean primed) {
private byte[] getClassBytes(String name) {
if (urlHelper == null || url == null)
return null;
return urlHelper.findSharedClass(null, url, name);
byte[] results = urlHelper.findSharedClass(null, url, name);
print(debug, () -> results != null ? "Found shared class bytes for: " + name + ' ' + url //$NON-NLS-1$
: "No shared class bytes found for: " + name + ' ' + url); //$NON-NLS-1$
return results;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@

package org.eclipse.osgi.internal.cds;

import java.util.function.Supplier;

import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.hookregistry.HookConfigurator;
import org.eclipse.osgi.internal.hookregistry.HookRegistry;
Expand All @@ -35,23 +38,33 @@ public class CDSHookConfigurator implements HookConfigurator {
private static final String OLD_CDS_CONFIGURATOR = "com.ibm.cds.CDSHookConfigurator"; //$NON-NLS-1$
private static final String J9_SHARED_CLASS_HELPER_CLASS = "com.ibm.oti.shared.SharedClassHelperFactory"; //$NON-NLS-1$

static void print(Debug debug, Supplier<String> msg) {
if (debug.DEBUG_LOADER_CDS) {
Debug.println(msg.get());
}
}
@Override
public void addHooks(HookRegistry hookRegistry) {
Debug debug = hookRegistry.getConfiguration().getDebug();
boolean disableCDS = Boolean.valueOf(hookRegistry.getConfiguration().getProperty(DISABLE_CDS));
if (disableCDS) {
print(debug, () -> "Class sharing is disabled by: " + DISABLE_CDS); //$NON-NLS-1$
return;
}
// check for the external com.ibm.cds system.bundle fragment
try {
Class.forName(OLD_CDS_CONFIGURATOR);
// the old com.ibm.cds fragment is installed; disable build-in one
print(debug, () -> "Detected old com.ibm.cds fragment."); //$NON-NLS-1$
return;
} catch (ClassNotFoundException e) {
// expected
}
try {
Class.forName(J9_SHARED_CLASS_HELPER_CLASS);
print(debug, () -> "Found Eclipse OpenJ9 support class: " + J9_SHARED_CLASS_HELPER_CLASS); //$NON-NLS-1$
} catch (ClassNotFoundException e) {
print(debug, () -> "Not running on Eclipse OpenJ9."); //$NON-NLS-1$
boolean reportErrors = Boolean.valueOf(hookRegistry.getConfiguration().getProperty(REPORT_ERRORS));
// not running on J9
if (reportErrors) {
Expand All @@ -63,8 +76,7 @@ public void addHooks(HookRegistry hookRegistry) {
}
return;
}

new CDSHookImpls().registerHooks(hookRegistry);
new CDSHookImpls(debug).registerHooks(hookRegistry);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@

package org.eclipse.osgi.internal.cds;

import com.ibm.oti.shared.HelperAlreadyDefinedException;
import com.ibm.oti.shared.Shared;
import com.ibm.oti.shared.SharedClassHelperFactory;
import com.ibm.oti.shared.SharedClassURLHelper;
import static org.eclipse.osgi.internal.cds.CDSHookConfigurator.print;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.hookregistry.BundleFileWrapperFactoryHook;
import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
import org.eclipse.osgi.internal.hookregistry.HookRegistry;
Expand All @@ -43,9 +43,20 @@
import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper;
import org.eclipse.osgi.storage.bundlefile.BundleFileWrapperChain;

import com.ibm.oti.shared.HelperAlreadyDefinedException;
import com.ibm.oti.shared.Shared;
import com.ibm.oti.shared.SharedClassHelperFactory;
import com.ibm.oti.shared.SharedClassURLHelper;

public class CDSHookImpls extends ClassLoaderHook implements BundleFileWrapperFactoryHook {
private static SharedClassHelperFactory factory = Shared.getSharedClassHelperFactory();

private final Debug debug;

public CDSHookImpls(Debug debug) {
this.debug = debug;
}

// With Equinox bug 226038 (v3.4), the framework will now pass an instance
// of BundleFileWrapperChain rather than the wrapped BundleFile. This is
// so that multiple wrapping hooks can each wrap the BundleFile and all
Expand All @@ -70,8 +81,17 @@ public void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, Cl
// 3) the bundle file for the classpath entry is of type CDSBundleFile
// 4) class bytes is same as passed to weaving hook i.e. weaving hook did not
// modify the class bytes
if ((null == clazz) || (false == hasMagicClassNumber(classbytes))
|| (null == getCDSBundleFile(classpathEntry.getBundleFile()))) {
if (null == clazz) {
print(debug, () -> "No class to store: " + name); //$NON-NLS-1$
return;
}
if ((false == hasMagicClassNumber(classbytes))) {
print(debug, () -> "Class was already stored: " + name); //$NON-NLS-1$
return;
}
CDSBundleFile cdsFile = getCDSBundleFile(classpathEntry.getBundleFile());
if (null == cdsFile) {
print(debug, () -> "No CDSBundleFile for class: " + name); //$NON-NLS-1$
return;
}
try {
Expand All @@ -90,6 +110,7 @@ public void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, Cl
// Class bytes have been modified by weaving hooks.
// Such classes need to be stored as Orphans, so skip the call to
// storeSharedClass()
print(debug, () -> "class bytes have changed, cannot store."); //$NON-NLS-1$
return;
}
}
Expand All @@ -98,8 +119,6 @@ public void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, Cl
return;
}

CDSBundleFile cdsFile = getCDSBundleFile(classpathEntry.getBundleFile());

if (null == cdsFile.getURL()) {
// something went wrong trying to determine the url to the real bundle file
return;
Expand All @@ -123,8 +142,11 @@ public void recordClassDefine(String name, Class<?> clazz, byte[] classbytes, Cl
}
if (null != urlHelper) {
// store the class in the cache
urlHelper.storeSharedClass(null, cdsFile.getURL(), clazz);
boolean successStore = urlHelper.storeSharedClass(null, cdsFile.getURL(), clazz);
print(debug, () -> successStore ? "Stored class: " + name : "Failed to store class: " + name); //$NON-NLS-1$//$NON-NLS-2$
cdsFile.setPrimed(true);
} else {
print(debug, () -> "No helper found to store class: " + name); //$NON-NLS-1$
}
}

Expand Down Expand Up @@ -217,9 +239,9 @@ public BundleFileWrapper wrapBundleFile(BundleFile bundleFile, Generation genera
if ((baseFile = getCDSBundleFile(baseFile)) != null) {
urlHelper = ((CDSBundleFile) baseFile).getURLHelper();
}
newBundleFile = new CDSBundleFile(bundleFile, urlHelper);
newBundleFile = new CDSBundleFile(bundleFile, debug, urlHelper);
} else {
newBundleFile = new CDSBundleFile(bundleFile);
newBundleFile = new CDSBundleFile(bundleFile, debug);
}

return newBundleFile;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.eclipse.osgi.internal.debug;

import java.io.PrintStream;

import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.util.SupplementDebug;
import org.eclipse.osgi.service.debug.DebugOptions;
Expand Down Expand Up @@ -48,6 +49,12 @@ public class Debug implements DebugOptionsListener {
* Loader Debug option key.
*/
public static final String OPTION_DEBUG_LOADER = ECLIPSE_OSGI + "/debug/loader"; //$NON-NLS-1$

/**
* Loader Debug option key.
*/
public static final String OPTION_DEBUG_LOADER_CDS = ECLIPSE_OSGI + "/debug/loader/cds"; //$NON-NLS-1$

/**
* Storage Debug option key.
*/
Expand Down Expand Up @@ -126,6 +133,10 @@ public class Debug implements DebugOptionsListener {
* Loader debug flag.
*/
public boolean DEBUG_LOADER = false; // "debug.loader"
/**
* Loader debug flag.
*/
public boolean DEBUG_LOADER_CDS = false; // "debug.loader"
/**
* Storage debug flag.
*/
Expand Down Expand Up @@ -199,6 +210,7 @@ public void optionsChanged(DebugOptions dbgOptions) {
DEBUG_BUNDLE_TIME = dbgOptions.getBooleanOption(OPTION_DEBUG_BUNDLE_TIME, false)
|| dbgOptions.getBooleanOption("org.eclipse.core.runtime/timing/startup", false); //$NON-NLS-1$
DEBUG_LOADER = dbgOptions.getBooleanOption(OPTION_DEBUG_LOADER, false);
DEBUG_LOADER_CDS = dbgOptions.getBooleanOption(OPTION_DEBUG_LOADER_CDS, false);
DEBUG_STORAGE = dbgOptions.getBooleanOption(OPTION_DEBUG_STORAGE, false);
DEBUG_EVENTS = dbgOptions.getBooleanOption(OPTION_DEBUG_EVENTS, false);
DEBUG_SERVICES = dbgOptions.getBooleanOption(OPTION_DEBUG_SERVICES, false);
Expand Down

0 comments on commit bb4e748

Please sign in to comment.