smallrye / jandex

Java Annotation Indexer

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Get all classes from a package

gsmet opened this issue · comments

I know Jandex is mostly about annotations but I was wondering if we could extend it a bit to keep an index of packages, subpackages and classes in these packages.

When building native applications with external libraries, it can happen that all the content of a package needs to be registered for reflection and that it is the only way to really be sure we do not forget anything and future-proof enough.

Listing classes manually is very cumbersome and brittle for large APIs.

Given the index is a closed world, it sounds feasible, right?

Thoughts?

Yes its totally feasable. It would introduce a memory cost, since indexes can get rather big so it might need to be an option (less of a problem for quarkus, more of a problem for wildfly).

However, the use case does raise a concern. The more you register for reflection the larger the rss size of the resulting binary. @Sanne recently went through the exercise of debugging a memory bloat issue in hibernate and this was the underlying cause (aggressively registering all fields and methods on entities). So I do worry we would make it too easy.

Perhaps the three of us can chat about it on Quarkus zulip?

This seems like a rather niche use case, and while I think both the persistent and runtime overhead are likely not that big (all the necessary DotNames must already exist for other reasons), I guess we could employ a strategy that doesn't affect the persistent format at all and only affects runtime footprint when used.

That is: we already have the full list of class names in the index (and they are all in the componentized form), so we can build the package structure from that. We could do it when finishing the index in memory or when loading a persistent index from file, but we could also do it on demand. Whenever the user calls one of the package-related methods, we'd build the package structure and store it for later usage.

WDYT?

OK, so I actually built a small prototype of that. It exposes this API:

/**
 * Returns all {@linkplain ClassInfo classes} known to this index that are present in given package.
 * Classes present in subpackages of given package are not returned.
 * If this index does not contain any classes in given package, returns an empty collection.
 *
 * @param packageName package name in the common, period-separated form (e.g. {@code com.example.foobar}),
 *        must not be {@code null}
 * @return immutable collection of classes present in given package, never {@code null}
 */
Collection<ClassInfo> getClassesInPackage(String packageName);

/**
 * Returns a set of packages known to this index that are direct subpackages of given package.
 * Indirect subpackages of given package (subpackages of a subpackage) are not returned.
 * If this index does not contain any classes in direct or indirect subpackages of given package, returns an empty
 * collection.
 *
 * @param packageName package name in the common, period-separated form (e.g. {@code com.example.foobar}),
 *        must not be {@code null}
 * @return immutable set of subpackages of given package, never {@code null}
 */
Set<String> getSubpackages(String packageName);

It uses Strings because that's actually easier to implement (DotName.packagePrefix() returns String), but I could make them DotNames too.

Any thoughts?

Since I had most of it done, I just went ahead and finished it. Done in #203.