Add support for shared libaries in class loader context.
For example:
PCL[a.dex:b.dex]{PCL[s1.dex]#PCL[s2.dex:s3.dex]};DLC[c.dex:d.dex]{DLC[s4.dex]}
Rewrite the class_loader_chain_ to be a chain instead of a vector,
to simplify processing and encoding of contexts.
bug: 111174995
Test: class_loader_context_test, test.py
Change-Id: I7c9f71b67a91b43ae534721b43dc4fdb8e0b6ec4
diff --git a/runtime/class_loader_context.h b/runtime/class_loader_context.h
index a4268aa..37cef81 100644
--- a/runtime/class_loader_context.h
+++ b/runtime/class_loader_context.h
@@ -154,10 +154,11 @@
// This will return a context with a single and empty PathClassLoader.
static std::unique_ptr<ClassLoaderContext> Default();
- private:
struct ClassLoaderInfo {
// The type of this class loader.
ClassLoaderType type;
+ // Shared libraries this context has.
+ std::vector<std::unique_ptr<ClassLoaderInfo>> shared_libraries;
// The list of class path elements that this loader loads.
// Note that this list may contain relative paths.
std::vector<std::string> classpath;
@@ -171,13 +172,35 @@
// After OpenDexFiles, in case some of the dex files were opened from their oat files
// this holds the list of opened oat files.
std::vector<std::unique_ptr<OatFile>> opened_oat_files;
+ // The parent class loader.
+ std::unique_ptr<ClassLoaderInfo> parent;
explicit ClassLoaderInfo(ClassLoaderType cl_type) : type(cl_type) {}
};
+ private:
// Creates an empty context (with no class loaders).
ClassLoaderContext();
+ // Get the parent of the class loader chain at depth `index`.
+ ClassLoaderInfo* GetParent(size_t index) const {
+ ClassLoaderInfo* result = class_loader_chain_.get();
+ while ((result != nullptr) && (index-- != 0)) {
+ result = result->parent.get();
+ }
+ return result;
+ }
+
+ size_t GetParentChainSize() const {
+ size_t result = 0;
+ ClassLoaderInfo* info = class_loader_chain_.get();
+ while (info != nullptr) {
+ ++result;
+ info = info->parent.get();
+ }
+ return result;
+ }
+
// Constructs an empty context.
// `owns_the_dex_files` specifies whether or not the context will own the opened dex files
// present in the class loader chain. If `owns_the_dex_files` is true then OpenDexFiles cannot
@@ -188,13 +211,13 @@
// Reads the class loader spec in place and returns true if the spec is valid and the
// compilation context was constructed.
bool Parse(const std::string& spec, bool parse_checksums = false);
+ ClassLoaderInfo* ParseInternal(const std::string& spec, bool parse_checksums);
- // Attempts to parse a single class loader spec for the given class_loader_type.
- // If successful the class loader spec will be added to the chain.
- // Returns whether or not the operation was successful.
- bool ParseClassLoaderSpec(const std::string& class_loader_spec,
- ClassLoaderType class_loader_type,
- bool parse_checksums = false);
+ // Attempts to parse a single class loader spec.
+ // Returns the ClassLoaderInfo abstraction for this spec, or null if it cannot be parsed.
+ std::unique_ptr<ClassLoaderInfo> ParseClassLoaderSpec(
+ const std::string& class_loader_spec,
+ bool parse_checksums = false);
// CHECKs that the dex files were opened (OpenDexFiles was called and set dex_files_open_result_
// to true). Aborts if not. The `calling_method` is used in the log message to identify the source
@@ -219,6 +242,20 @@
bool for_dex2oat,
ClassLoaderContext* stored_context) const;
+ // Internal version of `EncodeContext`, which will be called recursively
+ // on the parent and shared libraries.
+ void EncodeContextInternal(const ClassLoaderInfo& info,
+ const std::string& base_dir,
+ bool for_dex2oat,
+ ClassLoaderInfo* stored_info,
+ std::ostringstream& out) const;
+
+ bool ClassLoaderInfoMatch(const ClassLoaderInfo& info,
+ const ClassLoaderInfo& expected_info,
+ const std::string& context_spec,
+ bool verify_names,
+ bool verify_checksums) const;
+
// Extracts the class loader type from the given spec.
// Return ClassLoaderContext::kInvalidClassLoader if the class loader type is not
// recognized.
@@ -228,13 +265,8 @@
// The returned format can be used when parsing a context spec.
static const char* GetClassLoaderTypeName(ClassLoaderType type);
- // Returns the WellKnownClass for the given class loader type.
- static jclass GetClassLoaderClass(ClassLoaderType type);
-
- // The class loader chain represented as a vector.
- // The parent of class_loader_chain_[i] is class_loader_chain_[i++].
- // The parent of the last element is assumed to be the boot class loader.
- std::vector<ClassLoaderInfo> class_loader_chain_;
+ // The class loader chain.
+ std::unique_ptr<ClassLoaderInfo> class_loader_chain_;
// Whether or not the class loader context should be ignored at runtime when loading the oat
// files. When true, dex2oat will use OatFile::kSpecialSharedLibrary as the classpath key in