JAVA bytecode optimization - java

This is a basic question.
I have code which shouldn't run on metadata beans. All metadata beans are located under metadata package.
Now,
I use reflection API to find out whether a class is located in the the metadata package.
if (newEntity.getClass().getPackage().getName().contains("metadata"))
I use this If in several places within this code.
The question is: Should I do this once with:
boolean isMetadata = false
if (newEntity.getClass().getPackage().getName().contains("metadata")) {
isMetadata = true;
}
C++ makes optimizations and knows that this code was already called and it won't call it again. Does JAVA makes optimization? I know reflection API is a beat heavy and I prefer
not to lose expensive runtime.

You should of course check whether there really is a performance issue before putting any work into optimising. getClass() is probably quite fast already (faster than instanceof, anyway). You could probably cache the set of classes that are in the metadata package so you don't need to keep checking the package names.
If you really need to compare packages, you could find the metadata package once, using the Package.getPackage(String name) method, then for each object, call getClass().getPackage() as before, and compare the two package objects.
This is quicker and more elegant than checking for a string in the package name, but would probably not work correctly if there are multiple classloaders, as the Package objects wouldn't be equal (==) and Package doesn't over-ride .equals(). Thinking about it, it may not even be guaranteed to work on a single classloader, but I suspect that in practice you get the same Package instance rather than another copy - would be wise to check this first!, e.g:
String.class.getPackage() == Integer.class.getPackage() // should be true
Update if you check the source code for Class.getPackage(), Package.getPackage() and ClassLoader.getPackage() you can see that they cache the Package objects, so you should be safe comparing them when using a single classloader
One problem of a package-naming convention is that you have to enforce and maintain it throughout the codebase, which could become a maintenance problem over time. A more explicit way of identifying the classes might be better.
Alternative approaches to identify specific groups of classes include:
Making your metadata beans implement a marker interface
Using Java Annotations to mark metadata beans
Making all beans implement a common interface with a method that can be called to check whether the are in a specific category that you define. This is ugly as it's basically duplicating the type system, but would be fast since it doesn't need reflection.

Related

When I use java.lang.instrument.Instrumentation#redefineClasses(), should I pass an array to the function?

I used java.lang.instrument.Instrumentation#redefineClasses() to redefine existing classes. Sometimes, I need to redefine several classes.
If I redefine classes one by one, I will know which ones were successful and which ones failed.
But is it better to put classes redefined in an array together to get more correctness?
If I redefine class one by one, I will know which is success, which is
failed.
True.
But is it better to put classes redefined in an array together to get
more correctness?
I didn't get what you meant by more correctness! But, anyways from my understanding, using a set(array) of classes can be particularly helpful in the case where there is an interdependence of one class on other class. So, in this case you can re-define both classes by passing them in this method.
Also, Java Documentation of Interface Instrumentation says :
This method is used to replace the definition of a class without
reference to the existing class file bytes, as one might do when
recompiling from source for fix-and-continue debugging.
...
This method operates on a set in order to allow interdependent changes to more than one class at the same time (a redefinition of
class A can require a redefinition of class B).
But, do keep remember :
If this method throws an exception, no classes have been redefined.
It is much more performant to instrument classes in a batch compared to passing each class individually.
The JVM needs to halt the application for applying the redefinition which is a rather costly operation so it is worth grouping up.
Also, grouping allows for interdependent changes of classes.

Creating a unique class at runtime for use as a key in a HashMap

I understand this is a terrible hack, but I'm required to edit an external library to conform to our project's needs. The project I'm changing stores a map of classes to instances of said classes. The project's original intention is to make it impossible to have duplicate classes, but I require them. My solution is to apply a UniqueClass field to each relevant object, and then each object also have a reference to the class that I need to create an instance of. In this way, what the UniqueClass is doesn't actually matter at all, only that it's unique.
Now, I need a way to create a unique class at runtime to store in this map. Here are the options I see:
Generate and compile the actual .java files at runtime. I've actually implemented this and it works, but it's somewhat slow and requires JDK (doesn't work with JRE since it needs access to certain libraries). I don't want to require JDK configuration since non-devs will likely be using this functionality.
Generate a unique anonymous class. This works, but only with the first duplicate. Any additional duplicates are treated as the same as the original anonymous class (ClassBuilder$1). I've read here it's possible to have ClassBuilder$2 etc, but I don't know how to do that.
Object object = new Object(){};
return object.getClass();
Use a Proxy class. I don't really understand these but it had the same results as anonymous class above, since the javadocs state that if a proxy class already exists, it just returns that one.
Class proxyClass = Proxy.getProxyClass(inter.class.getClassLoader(), new Class[] { inter.class });
return proxyClass;
(Truly the most terrible way) Create a package of classes that are iterated through as each one is used as a UniqueClass. Ugly code, lots of unnecessary classes, and ultimately a limit on the number of duplicates possible.
Is there an elegant solution to this problem?
I am modifying the source code itself.
In that case create a wrapper object to use as the key in the Map. You can override equals() and hashCode() as necessary to achieve your goals. In essence you are adding one more layer of indirection to your existing multi-map of classes and instances.

Ways to signal that API returns an unmodifiable/immutable collection

Other than documenting it (obviously it should also be documented), using a special return type (I'm wary of limiting myself to an ImmutableX) or having the user find out at runtime, is there any other way of telling the users of an API that the collection they receive from said API is unmodifiable/immutable?
Are there any naming conventions or marker annotations that universally signal the same thing?
Edit: Unmodifiable and immutable do not mean the same thing, but for the purposes of this question, they are similar enough. The question basically boils down to letting the user know that the returned object does not fully honour its contract (ie. some common operations will throw a runtime exception).
Not a general naming convention but you might be interested in using this #Immutable annotation: http://aspects.jcabi.com/annotation-immutable.html
Besides the documentation purpose this mechanism will also validate if your object is really immutable (during it's instantiation) and throw a runtime exception if it is not.
Good and verbose solution would be to make your own UnmodifiableCollection wrapper class, and return it:
public UnmodifiableCollection giveMeSomeUnmodifableCollection() {
return new UnmodifiableCollection(new LinkedList());
}
The name of the return type would be enough to make verbose statement about the unmodifiablility of the collection.
Document it indeed
Provide API for checking if the given object is imutable collection
Return collection in wrapper that will hold information is the collection inside of it is mutable or not - my favorite solution
If possible, dont use mullable and immutable collections, but pick one of them. Results can always be immutable as they are results - why changing it. If there would be such need, it is a matter of single line to copy collection to new, mutable one and modify it (eg for chain processing)
Writing an #Immutable annotation on the return type of a method is the best approach. It has multiple benefits:
the annotation documents the meaning for users
a tool can verify that client code respects the annotation (that is, that client code does not have bugs)
a tool can verify that the library code respects the annotation (that is, that library code does not have bugs)
What's more, the verification can occur at compile time, before you ever run your code.
If you want verification at compile time, you can use the IGJ Immutability Checker. It distinguishes between
#Immutable references whose abstract value never changes, and
#ReadOnly references upon which side effects cannot be performed.

Replacing/Overriding Java "native" Classes?

I'm working with BigDecimals and I have the requirement that a division by 0 should not result in an ArithmeticException, but in returning 0 instead (weird business math).
This is a rather new requirement and we already have quite a bit of code, which uses BigDecimals in a lot of places. I don't want to go through all these places and implement zero checks. This also would not help me with 3rd party libraries, which might internally use BigDecimals and will throw an ArithmeticExceptioninstead.
I'd also like to set a default precision/scale and change the compareTo method to able to ignore small rounding errors.
Because of all these global changes which would create a lot of "boilerplate" code, I came up with the idea to change the implementation of BigDecimal. I've already done this before for other 3rd party classes to fix certain bugs myself.
I replaced those classes by creating a class with the same name in the same package like the 3rd party class, and because the external jar files will be loaded after my own classes, I was able to replace them.
But creating a java.math.BigDecimal didn't help me, because it seems that the "native" Java classes are loaded even before my own classes.
Let's assume that I really want every single BigDecimal in my application to work a bit different, how would I be able to replace the "official" BigDecimal? Am I allowed to do that, and could there be some other, technical problems I didn't think of now?
You have to put your classes in the "bootstrap" classpath if you want to override builtin classes. as to the wisdom of actually doing this (i.e. your changes will affect the entire jvm)...
BigDecimal is not final, so you could definitely extend it yourself, and change its behaviour (especially by overriding the divideXXX() methods).
You won't have to change the parameters etc., but remember to change the type of actually used objects! So you will use "your" methods.
As to compareTo() etc. you also won't have any problems - BigDecimal itself implements Comparable interface and has its own compareTo().

JVM bytecode limitations on class-class interactions

I was looking through the JVM bytecode instructions and was surprised to see that all the interactions between classes (e.g. casting, new, etc.) rely upon constant pool lookups for identity of the other classes.
Am I correct in inferring that this means that one class cannot know about the existence of more than 64k others, as it is impossible to refer to them? If one did need to refer to that many, what ought one do--delegate the work to multiple classes each of which could have their own <64k interactions?
(The reason this interests me is that I have a habit of writing code generators, sometimes producing thousands of distinct classes, and that some languages (e.g. Scala) create classes prolifically. So it seems that if true I have to be careful: if I have hundreds of methods in a class each using hundreds of (distinct) classes, I could exceed the constant pool space.)
Am I correct in inferring that this means that one class cannot know about the existence of more than 64k others, as it is impossible to refer to them?
I think you are correct. And don't forget that there are constant pool entries for other things; e.g. all of the classes method and fields names, and all of its literal strings.
If one did need to refer to that many, what ought one do--delegate the work to multiple classes each of which could have their own <64k interactions?
I guess so.
However, I'm not convinced that this concern would ever be realized in practice. It is hard to conceive of a class that needs to directly interact with that many other classes ... unless the code generator is ignoring the structure of its input source code.
It sounds like your problem could be solved via invokedynamic. This is basically a much faster form of reflection designed to ease the implementation of dynamic languages on the JVM.
If you really do have to deal with thousands of automatically generated classes, you probably don't want to statically link it all. Just use invokedynamic. This also has the advantage of letting you defer some code generation to runtime.
Note that you still need a constant pool entry for every dynamic method called by a class, but you no longer need to refer to the actual class and methods being called. In fact, you can create them on demand.

Categories