Let's say I wanted to assert that a given Java source folder contained all of the source code required to run any of the programs contained in the source folder. Simply showing that the whole source folder compiles would be insufficient because perhaps some of those programs use reflection to instantiate objects. As such I could search through all the code and look for invocations of newInstance()
to learn what classes are expected to be present at runtime. But what about calls to Class.forName(...)
that are not involved in calls to newInstance()
? Better check for those as well. But how many such things do I need to check for?
Is there any sort of exhaustive list I could consult to ensure that I am considering each way in Java that such a runtime dependency could be introduced? Restated, does there exist some list of operations such that if I can show none of the source in a source folder use those operations (and that folder compiles) that all (code) dependencies are present?
If no such list exists, could we start one in this thread and make a best effort to cover all operations that we know of?
Edit
I'd like to narrow the question a little. What I'm most interested in showing is that if a codebase compiles, all dependencies are present. It seems to me to do this I would need to first compile the codebase and then check to see if any of the code ever calls certain methods (e.g. newInstance
) that could introduce a runtime dependency. If no such methods are found, I'm reasonably sure that all required code is present in source form and running the program will not generate a ClassNotFoundException
.
Compiletime dependencies are only the dependencies (other classes) which you use directly in the class you're compiling. Runtime dependencies covers both the direct and indirect dependencies of the class you're running.
Declaring module dependencies Modules are usually stored in a repository, such as Maven Central, a corporate Maven or Ivy repository, or a directory in the local file system.
A Java class has a dependency on another class, if it uses an instance of this class. We call this a class dependency. For example, a class which accesses a logger service has a dependency on this service class. Ideally Java classes should be as independent as possible from other Java classes.
Answer to the original question
There is no extensive way You can do this as far as I know. I mean consider the following code:
public static Object calleableFromAnywhere(Object o) throws IllegalAccessException, InstantiationException {
Object ret = null;
if(!Objects.isNull(o)){
ret = o.getClass().newInstance();
}
return ret;
}
In this case You do not even know what kind of dependency You will have at runtime.
If you restrict your search to constructor based object creation only you have a lot of choices also:
Constructor<?> constructor = o.getClass().getConstructor();
//there could be a lot of constructors enclosing different paramethers
Object something = o.getClass().newInstance();
//default constructor called
And even those could be obtained by reflection... The rabbit hole is infinitely deep.
The call You mentioned Class.forName(...)
could take any parameter String
and those could be given from a database or an input field from the user.
I do not think it is possible to predict all the String
variables you could encounter at runtime. If you have anything like this You are not likely to succeed.
TL.DR.: there is no exact solution I know of. According to the question You are not only interested in newInstance
or instance creations as you could have static methods on classes as dependency as well. The idea is nice, but there is no 100% solution to this problem.
Narrowed/clarified questions answer
The a newInstance
call is not introducing a new dependency. It could be called on a loaded class definition only. (Basically you never get to the newInstance
if the class could not be loaded.) So if your goal is to answer with high certainty that if a class will not be represented is an another problem.
Altering the previous example shows that you are not likely to have the definit dependent classes:
public static Class getClass(String name) throws ClassNotFoundException {
return Class.forName(name);
}
As name
could be anything that you can recieve runtime. Also there is an other ways to load classes as the following example shows.
public Class getClassExample1(String name) throws ClassNotFoundException {
return this.getClass().getClassLoader().loadClass(name);
}
According to the JavaDoc of ClassNotFoundException
exception these places are using it:
Those are the places where it is thrown, but you have to check every path to those methods like someInstance.getClass(name)
.
In addition to runtime dependencies You can encounter NoClassDefFoundError
as well. If you are using some containers and set some dependencies as provided for example in maven You can also have some problems runtime, while the compilation was totally fine.
TL.DR.V2: You can only minimize the risk of not having a dependency with a static analysis, but if you want to try it you should check the mentioned methods and all of the call chains (even via reflection) that could lead to these.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With