Equivalent of #define in Java? - java

I'm writing a library that needs to have some code if a particular library is included. Since this code is scattered all around the project, it would be nice if users didn't have to comment/uncomment everything themselves.
In C, this would be easy enough with a #define in a header, and then code blocks surrounded with #ifdefs. Of course, Java doesn't have the C preprocessor...
To clarify - several external libraries will be distributed with mine. I do not want to have to include them all to minimize my executable size. If a developer does include a library, I need to be able to use it, and if not, then it can just be ignored.
What is the best way to do this in Java?

There's no way to do what you want from within Java. You could preprocess the Java source files, but that's outside the scope of Java.
Can you not abstract the differences and then vary the implementation?
Based on your clarification, it sounds like you might be able to create a factory method that will return either an object from one of the external libraries or a "stub" class whose functions will do what you would have done in the "not-available" conditional code.

As other have said, there is no such thing as #define/#ifdef in Java. But regarding your problem of having optional external libraries, which you would use, if present, and not use if not, using proxy classes might be an option (if the library interfaces aren't too big).
I had to do this once for the Mac OS X specific extensions for AWT/Swing (found in com.apple.eawt.*). The classes are, of course, only on the class-path if the application is running on Mac OS. To be able to use them but still allow the same app to be used on other platforms, I wrote simple proxy classes, which just offered the same methods as the original EAWT classes. Internally, the proxies used some reflection to determine if the real classes were on the class-path and would pass through all method calls. By using the java.lang.reflect.Proxy class, you can even create and pass around objects of a type defined in the external library, without having it available at compile time.
For example, the proxy for com.apple.eawt.ApplicationListener looked like this:
public class ApplicationListener {
private static Class<?> nativeClass;
static Class<?> getNativeClass() {
try {
if (ApplicationListener.nativeClass == null) {
ApplicationListener.nativeClass = Class.forName("com.apple.eawt.ApplicationListener");
}
return ApplicationListener.nativeClass;
} catch (ClassNotFoundException ex) {
throw new RuntimeException("This system does not support the Apple EAWT!", ex);
}
}
private Object nativeObject;
public ApplicationListener() {
Class<?> nativeClass = ApplicationListener.getNativeClass();
this.nativeObject = Proxy.newProxyInstance(nativeClass.getClassLoader(), new Class<?>[] {
nativeClass
}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
ApplicationEvent event = new ApplicationEvent(args[0]);
if (methodName.equals("handleReOpenApplication")) {
ApplicationListener.this.handleReOpenApplication(event);
} else if (methodName.equals("handleQuit")) {
ApplicationListener.this.handleQuit(event);
} else if (methodName.equals("handlePrintFile")) {
ApplicationListener.this.handlePrintFile(event);
} else if (methodName.equals("handlePreferences")) {
ApplicationListener.this.handlePreferences(event);
} else if (methodName.equals("handleOpenFile")) {
ApplicationListener.this.handleOpenFile(event);
} else if (methodName.equals("handleOpenApplication")) {
ApplicationListener.this.handleOpenApplication(event);
} else if (methodName.equals("handleAbout")) {
ApplicationListener.this.handleAbout(event);
}
return null;
}
});
}
Object getNativeObject() {
return this.nativeObject;
}
// followed by abstract definitions of all handle...(ApplicationEvent) methods
}
All this only makes sense, if you need just a few classes from an external library, because you have to do everything via reflection at runtime. For larger libraries, you probably would need some way to automate the generation of the proxies. But then, if you really are that dependent on a large external library, you should just require it at compile time.
Comment by Peter Lawrey: (Sorry to edit, its very hard to put code into a comment)
The follow example is generic by method so you don't need to know all the methods involved. You can also make this generic by class so you only need one InvocationHandler class coded to cover all cases.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
ApplicationEvent event = new ApplicationEvent(args[0]);
Method method = ApplicationListener.class.getMethod(methodName, ApplicationEvent.class);
return method.invoke(ApplicationListener.this, event);
}

In Java one could use a variety of approaches to achieve the same result:
Dependency Injection
Annotations
Reflection
The Java way is to put behaviour that varies into a set of separate classes abstracted through an interface, then plug the required class at run time. See also:
Factory pattern
Builder pattern
Strategy pattern

Well, Java syntax is close enough to C that you could simply use the C preprocessor, which is usually shipped as a separate executable.
But Java isn't really about doing things at compile time anyway. The way I've handled similar situations before is with reflection. In your case, since your calls to the possibly-non-present library are scattered throughout the code, I would make a wrapper class, replace all the calls to the library with calls to the wrapper class, and then use reflection inside the wrapper class to invoke on the library if it is present.

Use a constant:
This week we create some constants
that have all of the benefits of using
the C preprocessor's facilities to
define compile-time constants and
conditionally compiled code.
Java has gotten rid of the entire
notion of a textual preprocessor (if
you take Java as a "descendent" of
C/C++). We can, however, get the best
benefits of at least some of the C
preprocessor's features in Java:
constants and conditional compilation.

I don't believe that there really is such a thing. Most true Java users will tell you that this is a Good Thing, and that relying on conditional compilation should be avoided at almost all costs.
I'm don't really agree with them...
You CAN use constants that can be defined from the compile line, and that will have some of the effect, but not really all. (For example, you can't have things that don't compile, but you still want, inside #if 0... (and no, comments don't always solve that problem, because nesting comments can be tricky...)).
I think that most people will tell you to use some form of inheritance to do this, but that can be very ugly as well, with lots of repeated code...
That said, you CAN always just set up your IDE to throw your java through the pre-processor before sending it to javac...

"to minimize my executable size"
What do you mean by "executable size"?
If you mean the amount of code loaded at runtime, then you can conditionally load classes through the classloader. So you distribute your alternative code no matter what, but it's only actually loaded if the library that it stands in for is missing. You can use an Adapter (or similar) to encapsulate the API, to make sure that almost all of your code is exactly the same either way, and one of two wrapper classes is loaded according to your case. The Java security SPI might give you some ideas how this can be structured and implemented.
If you mean the size of your .jar file, then you can do the above, but tell your developers how to strip the unnecessary classes out of the jar, in the case where they know they aren't going to be needed.

I have one more best way to say.
What you need is a final variable.
public static final boolean LibraryIncluded= false; //or true - manually set this
Then inside the code say as
if(LibraryIncluded){
//do what you want to do if library is included
}
else
{
//do if you want anything to do if the library is not included
}
This will work as #ifdef. Any one of the blocks will be present in the executable code. Other will be eliminated in the compile time itself

Use properties to do this kind of thing.
Use things like Class.forName to identify the class.
Do not use if-statements when you can trivially translate a property directly to a class.

Depending on what you are doing (not quite enough information) you could do something like this:
interface Foo
{
void foo();
}
class FakeFoo
implements Foo
{
public void foo()
{
// do nothing
}
}
class RealFoo
{
public void foo()
{
// do something
}
}
and then provide a class to abstract the instantiation:
class FooFactory
{
public static Foo makeFoo()
{
final String name;
final FooClass fooClass;
final Foo foo;
name = System.getProperty("foo.class");
fooClass = Class.forName(name);
foo = (Foo)fooClass.newInstance();
return (foo);
}
}
Then run java with -Dfoo.name=RealFoo|FakeFoo
Ignored the exception handling in the makeFoo method and you can do it other ways... but the idea is the same.
That way you compile both versions of the Foo subclasses and let the developer choose at runtime which they wish to use.

I see you specifying two mutually exclusive problems here (or, more likely, you have chosen one and I'm just not understanding which choice you've made).
You have to make a choice: Are you shipping two versions of your source code (one if the library exists, and one if it does not), or are you shipping a single version and expecting it to work with the library if the library exists.
If you want a single version to detect the library's existence and use it if available, then you MUST have all the code to access it in your distributed code--you cannot trim it out. Since you are equating your problem with using a #define, I assumed this was not your goal--you want to ship 2 versions (The only way #define can work)
So, with 2 versions you can define a libraryInterface. This can either be an object that wraps your library and forwards all the calls to the library for you or an interface--in either case this object MUST exist at compile time for both modes.
public LibraryInterface getLibrary()
{
if(LIBRARY_EXISTS) // final boolean
{
// Instantiate your wrapper class or reflectively create an instance
return library;
}
return null;
}
Now, when you want to USE your library (cases where you would have had a #ifdef in C) you have this:
if(LIBRARY_EXISTS)
library.doFunc()
Library is an interface that exists in both cases. Since it's always protected by LIBRARY_EXISTS, it will compile out (should never even load into your class loader--but that's implementation dependent).
If your library is a pre-packaged library provided by a 3rd party, you may have to make Library a wrapper class that forwards it's calls to your library. Since your library wrapper is never instantiated if LIBRARY_EXISTS is false, it shouldn't even be loaded at runtime (Heck, it shouldn't even be compiled in if the JVM is smart enough since it's always protected by a final constant.) but remember that the wrapper MUST be available at compile time in both cases.

If it helps have a look at j2me polish or Using preprocessor directives in BlackBerry JDE plugin for eclipse?
this is for mobiles app but this can be reused no ?

Related

Java: runtime reflection or type introspection?

Is the following code considered to be runtime reflection or is it type introspection?
Class c = java.util.ArrayList.class;
String className = c.getName();
I want to use this in the compilation phase, and do not want to use any resources (including time) in runtime. Does it use any runtime resource?
It is both, as #StephenC already points out correctly.
To your request for a compile-time solution: There is a solution, but you'd need to implement your own Builder for that.
First off, some standard-Java implementations:
Because implementing and including your own Builder might be a lot of work for very little effect, here's a much easier answer: class initialization.
public class CompileTimeInit {
// option 1
static public final String ARRAYLIST_CLASS_NAME = java.util.ArrayList.class.getName();
// option 2
static public final String ARRAYLIST_CLASS_NAME_INIT_BLOCK;
static {
ARRAYLIST_CLASS_NAME_INIT_BLOCK = java.util.ArrayList.class.getName();
}
public static void main(final String[] args) {
System.out.println("1:\t" + ARRAYLIST_CLASS_NAME);
System.out.println("2:\t" + ARRAYLIST_CLASS_NAME_INIT_BLOCK);
// option 3
final Class c = java.util.ArrayList.class;
final String className = c.getName();
System.out.println("3:\t" + className);
}
}
static initialization will take its (very minimal) time in class intialization. This is part of the runtime, but it will only take place once a class is referenced/metnioned in some code that gets executed. This initialization will only be done once (per classloader loaded class) and is considered really fast.
Now, to the real compile-time implementations:
You can have really advanced builders implemented, like Project Lombok does, along with integration into IDEs, compilers, build tools, platforms. Check out their page, top menu, "Install", to see the options available.
You can write your own builder and include it into the build cycle of your build cycle. The best way to do it is via an Annotaion "Pre"-Processor.
The third option is to write a complete standalone application. This means you have to implement:
opening .java source files
scanning for your Interfaces or Annotations
replacing the code with the calculated contents
saving .java source files
let the compilation phase continue
and include that into you build cycle. This is also partially described in the article above
I would have said that it is BOTH runtime reflection AND type introspection.
Note that the [introspection] tag defines introspection as:
"A capability of some object-oriented programming languages to determine the type of an object at runtime."
You could also say that your example uses (runtime) reflection to perform type introspection.
I want to use this in the compilation phase.
It is possible to examine types at compile time in an annotation processor. However, I suspect that the effort involved in doing that would be prohibitive. You need to be able to spot a specific pattern in two statements and then replace the statements with something else.
(Have you benchmarked the class name lookup to see how much time it actually takes? I would have thought it was just a few nanoseconds. Not enough to be significant.)

ByteBuddy agent to replace one method param with another

I have a large 3rd party code base I can't modify, but I need to make a small but important change in many different places. I was hoping to use a ByteBuddy based agent, but I can't figure out how. The call I need to replace is of the form:
SomeSystemClass.someMethod("foo")
and I need to replace it with
SomeSystemClass.someMethod("bar")
while leaving all other calls to the same method untouched
SomeSystemClass.someMethod("ignore me")
Since SomeSystemClass is a JDK class, I do not want to advise it, but only the classes that contain calls to it. How can this be done?
Note that:
someMethod is static and
the calls (at least some of them) are inside a static initializer block
There are two approaches to this with Byte Buddy:
You transform all classes with the call site in question:
new AgentBuilder.Default()
.type(nameStartsWith("my.lib.pkg."))
.transform((builder, type, loader, module) -> builder.visit(MemberSubstitution.relaxed()
.method(SomeSystemClass.class.getMethod("someMethod", String.class))
.replaceWith(MyAlternativeDispatcher.class.getMethod("substitution", String.class)
.on(any()))
.installOn(...);
In this case, I suggest you to implement a class MyAlternativeDispatcher to your class path (it can also be shipped as part of the agent unless you have a more complex class loader setup such as OSGi where you implement the conditional logic:
public class MyAlternativeDispatcher {
public static void substitution(String argument) {
if ("foo".equals(argument)) {
argument = "bar";
}
SomeSystemClass.someMethod(argument);
}
}
Doing so, you can set break points and implement any complex logic without thinking too much of byte code after setting up the agent. You can, as suggested, even ship the substitution method independently of the agent.
Instrument the system class itself and make it caller sensitive:
new AgentBuilder.Default()
.with(RedefinitionStrategy.RETRANSFORMATION)
.disableClassFormatChanges()
.type(is(SomeSystemClass.class))
.transform((builder, type, loader, module) -> builder.visit(Advice.to(MyAdvice.class).on(named("someMethod").and(takesArguments(String.class)))))
.installOn(...);
In this case, you'd need to reflect on the caller class to make sure you only alter behavior for the classes you want to apply this change for. This is not uncommon within the JDK and since Advice inlines ("copy pastes") the code of your advice class into the system class, you can use the JDK internal APIs without restriction (Java 8 and prior) if you cannot use the stack walker API (Java 9 and later):
class MyAdvice {
#Advice.OnMethodEnter
static void enter(#Advice.Argument(0) String argument) {
Class<?> caller = sun.reflect.Reflection.getCallerClass(1); // or stack walker
if (caller.getName().startsWith("my.lib.pkg.") && "foo".equals(argument)) {
argument = "bar";
}
}
}
Which approach should you choose?
The first approach is probably more reliable but it is rather costly since you have to process all classes in a package or subpackages. If there are many classes in this package you will pay quite a price for processing all these classes to check for relevant call sites and therefore delay application startup. Once all classes are loaded, you have however paid the price and everything is in place without having altered a system class. You do however need to take care of class loaders to make sure that your substitution method is visible to everybody. In the simplest case, you can use the Instrumentation API to append a jar with this class to the boot loader what makes it globally visible.
With the second approach, you only need to (re-)transform a single method. This is very cheap to do but you will add a (minimal) overhead to every call to the method. Therefore, if this method is invoked a lot on a critical execution path, you'd pay a price on every invocation if the JIT does not discover an optimization pattern to avoid it. I'd prefer this approach for most cases, I think, a single transformation is often more reliable and performant.
As a third option, you could also use MemberSubstitution and add your own byte code as a replacement (Byte Buddy exposes ASM in the replaceWith step where you can define custom byte code instead of delegating). This way, you could avoid the requirement of adding a replacement method and just add the substitution code in-place. This does however bear the serious requirement that you:
do not add conditional statements
recompute the stack map frames of the class
The latter is required if you add conditional statements and Byte Buddy (or anybody) cannot optimize it in-method. Stack map frame recomputation is very expensive, fails comparable often and can require class loading locks to dead lock. Byte Buddy optimizes ASM's default recomputation, trying to avoid dead locks by avoiding class loading but there is no guarantee either, so you should keep this in mind.

Initialize (load) a java class with a java.lang.Class<T> instance

I have to admit that this is more a cosmetic issue, but the fact that I haven't found a more straight-forward solution makes me think I am probably missing something.
The thing is, my class (let's say Foo) has a very important static block where it registers itself (Foo.class) with a builder method in a Map, like this:
// somewhere in the class
static {
Bar.registerBuilder(Foo.class, Foo::build);
}
This makes it possibe to get a Foo builder from the Bar class, a bit like this:
// somewhere in a method
Foo foo = Bar.getBuilder(Foo.class).apply("Hello World");
(if the builder takes a String argument). However, the upper code example will only work if the Foo class was already initialized. If not, this means the static block of Foo wasn't executed and the builder isn't registered in Bar by now, which is leading to getBuilder() returning null and apply() throwing a NullPointerException.
Thanks to the internet (mostly StackOverflow) I found out that you can imperatively with Class.forName(String). But what really confuses me is that this method takes a String (therefore throws the checked ClassNotFoundException) and I haven't found a way to load and initialize a class directly via a java.lang.Class instance. I would have expected something like
Class<Foo> clazz = Foo.class;
clazz.load(); // does not exist
Instead I have to do this:
Class<Foo> clazz = Foo.class;
try {
Class.forName(clazz.getName());
} catch (ClassNotFoundException) {
// handle an exception that is actually unreachable
}
I would like to know if I am completely missing something, or if not, if there is a cleaner way to load and initialize a class via the java.lang.Class representation.
Any help is appreciated, thank you!
EDIT 1: As #Boris the Spider pointed out in the comments, Foo.class should probably already load and initialize the class, but it doesn't (in my case, at least) and that's why I even encountered this problem.
EDIT 2: Using the "complicated" way to load the class via Class.forName() (as in the code example) actually resolves the problem as I thought. It's just that I'd like to use a cleaner way if possible.
Using:
Java 11 (openjdk 11.0.2)
IntelliJ IDEA Ultimate (2019.3)
Maven (3.6.3)
If you are already referencing the class it would be much better to move that static code into normal static factory method. As why would you use reflections or try to reference some class just to make some code run when you can just run that method?
public static BuilderFunction createBuilder() {
return Foo::build;
}
And just call it in static block of Bar:
registerBuilder(Foo.class, Foo.createBuilder());
If you need something more dynamic you can use service loaders, especially with java 9+ as they are much nicer now to use:
provides my.BuilderProvder with something.FooProvider;
And just load them all in Bar:
ServiceLoader<BuilderProvder> loader = ServiceLoader.load(BuilderProvder.class);
loader.stream()
.forEach(provider -> registerBuilder(provider));
now even different modules not developed by you can provide own builders and you don't need to do any manual class loading (and class initialization is only guaranteed to happen if class is actually used, like some method or field used - note that constants are inlined at compilation so they don't count).
You can also use some hacky reflection libraries like ClassGraph or Reflections to get all classes of given type/with given annotation and then load them and invoke some init method on them all just like in my first proposed solution with createBuilder. This is how many components inside spring are registered, similar thing can be done with java annotation preprocessing to find this classes at compile time and just save the names. But if possible I would suggest sticking to existing build in solutions like service loaders.

Java dependency injection using ASM or CGLib

I have a fairly large Java code base (~15k files) that I do not have access to the source for, however, I would like to modify certain classes at runtime and inject code into certain methods to also call my code.
Due to technical issues, I can't decompile/recompile and go from there. The class files are loaded by native code and are extracted from a custom archive format and loaded using a custom class loader. I can however execute Java code in the context of their JVM instance fairly easily.
My goal is to do something like below:
For example, say in there code there is a class:
class Theirs {
public Theirs() {
//....
}
public String getName() {
return "Theirs";
}
}
And in my code I have:
class Mine
{
public static Theirs theirs_ = null;
public static void myMethod(Theirs theirs) {
theirs_ = theirs;
}
}
I would like to modify every instance of Theirs to behave as such:
class Theirs {
public Theirs() {
Mine.myMethod(this);
}
}
So that I can then do something like:
System.out.println(Mine.theirs_.getName());
I thought that CGLib Proxies would enable this, but with Proxies, the overhead is high due to string comparisons for methods that may be called hundreds thousands of times a second and anyways, I discovered that in order to have an instance of an enhanced object, you need to instantiate them yourself.. IE: not all instances of the class you enhanced are actually enhanced such as:
public static void main( String[] args )
{
Object proxy = Enhancer.create(Object.class, new HashCodeAlwaysZeroMethodInterceptor());
System.out.println(new Object().hashCode());
System.out.println(proxy.hashCode());
}
The first println prints a real objects hash, not 0 as intended.
So now I am thinking that what I need to do is write my own (or modify theirs) ClassLoader that looks for the classes I am interested in modifying, inject my modifications and go from there using something like ASM. (I've done something similar using JVMTI and C++, but the compile/debug process for that is extremely time consuming)
Before I do that however, I was hoping that there was something that worked similar to how CGLib proxies work, in that the library takes care of the required bytecode modifications, but that doesn't require me to actually instantiate an instance of said enhanced class.
I don't know if CGLIB is ideal for injecting Java code into Java classes - but there are a couple of framework like f.e. javassist available which provide a Java centric way to inject code into non-sealed Java classes: http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
For example, I had to create a Plugin mechanism for a university course once where I used javassist therefore. Hope the code example is helpful: https://github.com/RovoMe/PluginApplication/blob/master/PluginFramework/PluginCore/src/main/java/at/rovo/core/classloader/InjectionLoaderStrategyDecorator.java

How to change a method's behavior according to the application which is calling it?

I have a common jar that uses some unmarshaling of a String object. The method should act differently depending on which application it is called from, how can I do that besides from the fact that I can identify the application by trying to load some unique class it has (don't like that). Is there some design pattern that solves this issue?
As I alluded to in my comment, the best thing to do is to break that uber-method up into different methods that encapsulate the specific behaviors, and likely also another method (used by all of the app-specific ones) that deals with the common behaviors.
The most important thing to remember is that behavior matters. If something is behaving differently in different scenarios, a calling application effectively cannot use that method because it doesn't have any control over what happens.
If you still really want to have a single method that all of your applications call that behaves differently in each one, you can do it, using a certain design pattern, in a way that makes sense and is maintainable. The pattern is called "Template Method".
The general idea of it is that the calling application passes in a chunk of logic that the called method wraps around and calls when it needs to. This is very similar to functional programming or programming using closures, where you are passing around chunks of logic as if it were data. While Java proper doesn't support closures, other JVM-based languages like Groovy, Scala, Clojure, JRuby, etc. do support closures.
This same general idea is very powerful in certain circumstances, and may apply in your case, but such a question requires very intimate knowledge of the application domain and architecture and there really isn't enough information in your posted question do dig too much deeper.
Actually, I think a good OO oriented solution is, in the common jar, to have one base class, and several derived classes. The base class would contain the common logic for the method being called, and each derived class would contain specific behavior.
So, in your jar, you might have the following:
public abstact class JarClass {
public method jarMethod() {
//common code here
}
}
public class JarClassVersion1 extends JarClass {
public method jarMethod() {
// initiailzation code specific to JarClassVerion1
super.jarMethod();
// wrapup code specific to JarClassVerion1
}
}
public class JarClassVersion2 extends JarClass {
public method jarMethod() {
// initiailzation code specific to JarClassVerion2
super.jarMethod();
// wrapup code specific to JarClassVerion2
}
}
As to how the caller works, if you are willing to design your code so that the knowledge of which derived class to use resides with the caller, then you obviously just have the caller create the appropriate derived class and call jarMethod.
However, I take it from your question, you want the knowledge of which class to use to reside in the jar. In that case, there are several solutions. But a fairly easy one is to define a factory method inside the jar which creates the appropriate derived class. So, inside the abstract JarClass, you might define the following method:
public static JarClass createJarClass(Class callerClass) {
if (callerClass.equals(CallerClassType1.class)) {
return new JarClassVersion1();
} else if (callerClass.equals(CallerClassType2.class)) {
return new JarClassVersion1();
// etc. for all derived classess
}
And then the caller would simply do the following:
JarClass.createJarClass(this.getClass()).jarMethod();

Categories

Resources