Summary: When I load and run one jar from another jar and that loaded jar attempts to access its resources inside itself, it is unable to find those resources. I believe this is because it is looking inside the jar that loaded it instead of itself. How can I fix this?
The problem in more detail:
I am attempting to programmatically load a jar file -- let's call it "Server" -- into the Java Virtual Machine through my own Java program -- let's call it "ServerAPI" -- and use extension and some other tricks to modify the behavior of and interact with Server. ServerAPI depends on Server, but if Server is not present, ServerAPI still has to be able to run and download Server from a website.
To avoid errors caused by ServerAPI loading without satisfying its dependencies from Server, I have made a launcher -- let's call it "Launcher" -- that is intended to download Server and set up ServerAPI as necessary, then load Server and ServerAPI, then run ServerAPI.
I have gotten to the point where Launcher is successfully able to load Server and ServerAPI. However, when I attempt to run Server through ServerAPI, errors appear because Server is unable to locate certain resources. There resources are located inside the Server jar as they always are.
I had the idea that perhaps, since the resource paths all seem to be relative, Java is searching for these resources inside the jar that initially loaded and ran the entire program, i.e. Launcher. To test this, I took some of those missing resources from the Server jar and put them in the same path in the Launcher jar. The errors related to those missing resources disappeared.
So, then, I need a way to ensure that all resources loaded by code in the Server are found in that jar instead of making Java search for them in the Launcher jar. Copying the assets into the Launcher jar worked for my test, but it would be inconvenient and error-prone for the final product, not to mention the fact that it would increase file sizes as there are a large number of resources to copy and that making multiple copies of the same files could lead to errors under certain circumstances.
Ideas that I have already thought of that will not work:
I cannot copy the resources into the Launcher jar because it would increase the size of Launcher; it further complicates the program and can potentially cause errors in cases where sometimes Server is run on its own and sometimes it is run through ServerAPI using Launcher; and it would not allow ServerAPI to be adapted for use with more than one version of Server.
I cannot move all the resources out of Server and into Launcher to eliminate redundancies and ambiguity because for complicated legal reasons, I cannot modify Server. I can, however, modify Launcher or ServerAPI freely, for I created them.
I cannot modify the paths of the resource calls. My tricks for modifying the behavior of Server using ServerAPI will not work in these sections of the code and even if they did, there are so many calls to so many resources that it would take ages to find them all and modify them all.
Research I have already done on this problem:
This question is the only question I've found that seems to be related to the issue, but I cannot modify each call to the resources for the reason mentioned in the paragraph above.
//EDIT:
It seems that Server's resource calls primarily use the format CLASS.class.getResourceAsStream("/RESOURCE")
. Does this help at all?
//END EDIT
//EDIT 2:
I tried using Thread.currentThread().setContextClassLoader()
to set the ClassLoader
to the one I used to load Server, hoping that since I was using the ClassLoader
used to load Server that all resource paths would now be relative to Server. Unfortunately, this did not work.
//END EDIT
//EDIT 3:
Up until now, I was initializing the parent of the ClassLoader
used to load Server to be Launcher's own ClassLoader
, so I just tried setting the parent to null
instead to make it act as a standalone ClassLoader
, hoping that would break its bond to Launcher. That didn't work either.
//END EDIT
Any help would be greatly appreciated! Thanks in advance!