1

I have a memory class loader (here) that I am using in a custom Minecraft launcher.

Memory Class Loader

Whenever I load up Minecraft (a Java LWJGL game), I am getting the following error:

27 achievements
182 recipes
Setting user
LWJGL Version: 2.4.2
java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at lc.<init>(SourceFile:21)
at gi.<init>(SourceFile:10)
at net.minecraft.client.Minecraft.a(SourceFile:254)
at net.minecraft.client.Minecraft.run(SourceFile:657)
at java.lang.Thread.run(Unknown Source)

I am creating the class loader like this:

Base.cLoader = new CLoader(
    GameUpdater.classLoader,
    new JarInputStream(new ByteArrayInputStream(jarFileBytes)));

As you can see, it manages to load up the first part then suddenly after LWJGL Version it crashes with "input == null".

Edit - Here is the new getResource method.
The error is on "URL()", as shown.

Image

Code:

public URL getResource(final String name) {
    URL url = new URL() { public InputStream openStream() {
        return new ByteArrayInputStream((byte[])others.get(name));
    }};

    return url;
}

2 Answers 2

3

A wild guess... it could be this: Warning: URLs for this are not yet implemented! You cannot call getResource() or getResources()!

So your code expects to retrieve an image from the JAR using the unimplemented method. An equivalent of this is probably being executed:

ImageIO.read(memClassLoader.getResource(someString));

Except that, as we have seen, the Error thrown from getResource is getting ignored and null being used as the value. ImageIO.read goes like this:

public static BufferedImage read(URL input) throws IOException {
    if (input == null) {
        throw new IllegalArgumentException("input == null!");
    }

    InputStream istream = null;
    try {
        istream = input.openStream();
    } catch (IOException e) {
        throw new IIOException("Can't get input stream from URL!", e);
    }
}

Sounds familiar? So, this is roughly what you need to implement:

public URL getResource(final String name) {
  try {
    return new URL("", "", 0, "",
        new URLStreamHandler() { public URLConnection openConnection(URL url) {
          return new URLConnection(url) {
            public void connect() {}
            public InputStream getInputStream() {
              // return the appropriate InputStream, based on the name arg
            }
          };
        }});
  } catch (MalformedURLException e) { throw new RuntimeException(e); }
}
Sign up to request clarification or add additional context in comments.

15 Comments

I'll try adding a custom "getResource" method then... you may be exactly right! Haha.
I'm having trouble making the actual getResource() method as I have no idea where to start. Any ideas?
Yes, it is getting called right before the error message. It's definitely the getResource() method that is the problem. It's just, I have no idea what I can do form this point. It is written in the comment "Note that you cannot - * acquire a class file as a resource (URL or stream)." so how can we obtain the resource URL. :S
The comment you cited is not the issue. You cannot acquire a class file, but you can acquire everything else -- that's what the class doc says and that's what you can see going on in getResourceAsStream. As for implementing getResource... note it returns a URL, not the actual contents of the resource. There are already some pointers in the comments there...
Updated the answer with more ideas.
|
0

The MemoryClassLoader is pretty much broken. It does not implement getResource() (as stated in the comment in the source), and also it does not define Packages for the classes it loads (this may or may not break an application).

Most likely that ClassLoader was quickly hacked for testing purposes, leaving the more complicated methods out.

Implementing your own URL protocol to handle getResource() is not too difficult, in getResource() you return an URL that uses a custom protocol name (e.g. "myclassloader://resourcename"), and also a custom implementation of URLStreamHandler that handles that protocol. That may not cover all the loopholes that might cause trouble in locating a resource, if the code loaded through the ClassLoader uses URL.toString() and converts it back it will still break.

Implementing a fully working ClassLoader that does not simple delegation to existing ClassLoaders, is not as simple as most examples make it look.

2 Comments

Interesting, are there any examples of doing this? I am completely new to the ClassLoader scene. I would really like to get a MemoryClassLoader working although if it is going to be hard then I'm going to just have to load it normally. :/
I don't know of any fully working examples - I hacked my own ClassLoader and that most likely still doesn't handle all the possible use cases. While testing it I ran into the getResource() and "no packages defined" issues myself, both of which broke the application I needed to run.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.