문제

What is the issue? I'm a Minecraft server admin/ server host / plugin developer, but find it an absolute annoyance to have to update my own personal plugins on every new release of the core game. It wasn't always like this, I've had plugins work across 20 versions without breaking in the past. To have to sit by and update 40 plugins once every month is, as you can imagine, an unneeded annoyance in my life considering I've never had to do this in the past.

What is causing the issue? Upon each new release, they require you to use different imports in your compiled jar files, thus forcibly breaking any outdated (but possibly still working) jar files. Believe me. I can read an error log and know when I need to actually go out and download a new update. I don't need to be protected from myself right now. It's just a game, I don't have much riding on it.

So what do I want to do about it? To this end, I'd like to make a simple program that automatically updates all my plugins for me. (Plugins come in the form of packaged .jar files.) It needs to do the following:

  1. Get a list of all jar files in X_Folder
  2. for each jar file, get all classes encased.
  3. for each class file, search for any instance of Y_STRING and replace it with Z_STRING.
  4. make sure everything gets put back into the jar files correctly.
  5. done.

Question? How would I code the class file editing method? I don't even know how to begin.

Disclaimer Sorry for sounding like I haven't even begun working on this. I just, don't have any experience with byte code manipulation. I've seen a few examples, but haven't seen anything about renaming imports yet. Hopefully someone here can help me. Thank you!

도움이 되었습니까?

해결책

  1. Get a list of all jar files in X_Folder
  2. for each jar file, get all classes encased.
  3. for each class file, search for any instance of Y_STRING and replace it with Z_STRING.
  4. make sure everything gets put back into the jar files correctly.
  5. done.

1) This is basic file manipulation. Look into java.io.File#listFiles() or its overloads.

2) a JAR file is a ZIP file with specific contents. Look into java.util.jar.JarFile or java.util.zip.ZipInputStream; Iterate over its entries (JarFile#entries()) and decompress each class file within (JarFile#getInputStream(ZipEntry)).

3) The class file is a binary format but it's documented very well. The general layout is documented on wikipedia: http://en.wikipedia.org/wiki/Java_class_file#General_layout

Of special interest is the Constant pool, which starts at byte 10 of the class file and enumerates all constants referred to from within the class file. It is, again, documented on Wikipedia: http://en.wikipedia.org/wiki/Java_class_file#The_constant_pool . Its number of entries is stored in bytes 8 and 9 (big-endian).

Of special interest within the constant pool are strings and class references.

Strings are identified by the first byte being 1. The next two bytes are the byte length of the string, and the remaining bytes are in UTF-8 (almost). Unlike UTF-8, higher planes are stored as surrogate pairs (6 bytes instead of 4) and the code point 0 is stored denormalised.

A class reference is nothing but a pointer to the constant pool, pointing to the class' fully qualified name. The fully qualified name is stored with forward slashes instead of dots to separate the fully qualified name (java/lang/Object). It's marked as the type 7.

Other entries in the constant pool: types 3,4,9-12 are four-byte, types 7 and 8 are two-byte. Types 5 and 6 are eight-byte but they also take up two slots in the constant pool.

The rest of the class file doesn't seem to mind if the byte length of the constant pool changes. Adding entries at the end of the constant pool seems safe as well (be sure to update the constant pool length).

4) Since a jar file is just a zip file, all you need is to repackage the original file with the updated contents. I don't expect this to be possible in-place, so you might need some file shuffling. Look into java.util.zip.ZipOutputStream for the implementation.

다른 팁

I could decompile their plugins, load them into an IDE and manually update them, but I'd prefer to have a more global solution, you know? Besides, this is a good opportunity to learn a new skill in Java.

I think that the skills you should be learning are:

  • build tools (e.g. Ant or Maven) that allow you to rebuild from source loading the code into an IDE, and

  • how to use a stream editor (e.g. sed or awk) to update your source code or a macro-preprocessor (e.g. cpp or m4) to generate the source code.

However, given the nature of the Minecraft platform, I'd not recommend it as a good place to learn Java / Java skills. Certainly, hacking / tweaking / massaging bytecode files is a skill that most professional Java developers would NOT normally need or use.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top