0

Let's say that I have a designated class that contains only static fields and methods.

class Utils {
    public static final String FOO = "foo";

    public static void bar() {
        System.out.println("Something");
    }
}

Now, here's a class that references some methods and constants from it:

class Main {
    public static void main(String[] args) {
        String s = Utils.FOO;
        Utils.bar();
    }
}

How can I make Maven copy those referenced members and produce a "fat" bytecode class that wouldn't rely on the original class that contained them? Those changes would only be applied right before compilation and wouldn't be reflected the source code itself, but they would essentially look like:

class Main {
    public static final String FOO = "foo";

    static void bar() {
        System.out.println("Something");
    }

    public static void main(String[] args) {
        String s = FOO;
        bar();
    }
}

EDIT: If making a custom Maven plugin is the only solution, then I would appreciate some examples of preprocessing Java code just before it gets passed to the compiler.

EDIT2: I solved this problem by making two custom Python scripts and attaching them to the lifecycle with exec-maven-plugin. The first one copies static fields and methods from designated package and pastes them where they're referenced, the second one reverts those changes right after the build is done.

  • 2
    Can you explain why you want to do this? – tgdavies May 18 '22 at 12:58
  • I need a compiled class file that can be serialised and ran on a different JVM instance that doesn't have the static Utils class loaded. – big_pp_energy May 18 '22 at 13:19
  • 1
    The value of `FOO` is copied anyway, without leaving a reference to the field. Besides that, it’s not clear why you can’t put the class file of the `Utils` class alongside the class file of the `Main` class. Having a single class file only doesn’t work for anything but the most trivial programs. – Holger May 18 '22 at 14:17
  • The point is that every "module" has to be a single, self-contained class. I can't just serialise and send multiple classes. – big_pp_energy May 18 '22 at 15:43
  • 1
    Why not? It seems like you are trying to solve the problem at the wrong end. If you have code to transfer one class file, you can expand it to transfer multiple class files. That’s easier than attempting code transformation which will fail anyway when the code is too complex. Class files have lots of limits, max number of fields, max number of methods, max number of constants (incl. class and members names and type signatures), etc. And you’d have to generate new names for disambiguation. – Holger May 18 '22 at 16:14
  • Because each module is uploaded trough a web form that takes a single base64 encoded .class file and a YAML config. There's no way to serialise more classes into a single base64 file in a way that would be recognised. – big_pp_energy May 18 '22 at 16:58
  • Lombok might be a good example to look at. – tgdavies May 19 '22 at 04:06
  • 1
    It would be useful to know more about this specific environment. As said, the approach of copying all members into a single class file is very limited. It only works for static members and may hit the class file’s maximum number of elements easily. In contrast, [there’s practically no limit](https://stackoverflow.com/a/42299271/2711488) for storing arbitrary data into a single class file, like embedding an entire library. But it requires `getResource("MyClass.class")` working in the target environment and the permission to create new class loaders. – Holger May 19 '22 at 07:19

0 Answers0