I have a legacy app that I am trying to convert from JDK8 to JDK12. One of the places I am having trouble is with the following code...
import jdk.nashorn.internal.ir.annotations.Immutable;
import java.util.Base64;
#Immutable // <-here
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_NULL)
public final class Application {
....
}
When I try to build with IntelliJ I get...
Error:(6, 43) java: package jdk.nashorn.internal.ir.annotations does not exist
Error:(10, 2) java: cannot find symbol
symbol: class Immutable
The code is not easy to follow and I am not sure what this is being used for, but a quick Google search suggests it allows Java to run ES5. It also seems to be deprecated and will be removed soon. Finally it is ES5 and not ESNext so I would like to use something a bit newer.
What is this being used for (my guess is JSON serialization but why not use GSON or Jackson?)
What can I replace it with that will be Java 12+ compatible?
If I remove it the following test fails...
#Test
public void equalsTest() {
EqualsVerifier.forClass(EvaluationResult.class).verify();
}
With the following error message...
[ERROR] EvaluationResultTest.equalsTest:42 Mutability: equals depends on mutable field id.
For more information, go to: http://www.jqno.nl/equalsverifier/errormessages
A search for EqualsVerifier turned up this documentation about its concept of immutability.
If you can’t make the fields final, but you’re absolutely certain that the class is immutable, you can add an #Immutable annotation to the class. It doesn’t matter where the annotation comes from; you can even write one yourself, as long as it’s called Immutable.
So it appears the Nashorn #Immutable annotation was only being used for convenience, and any annotation of the same name would do as well, even one defined in your own project:
package my.legacy.project.annotations;
/**
* Tag for classes that are immutable.
*/
public #interface Immutable {
//empty
}
Alternatively, if you can make all the fields of EvaluationResult and the fields of all the objects it contains final, the documentation indicates the annotation will not be needed, but you may not be able to make Application immutable if it needs to be used with JSON, depending on the JSON library used.
Related
I was using Google Dataflow and have encountered an error of
java.lang.IllegalArgumentException: unable to serialize ...
from SerializableUtils.class even I have serialVersionUID defined. I suspected the reason could be that I import non standard java library which is not listed on JRE Class While List . In my case I import javassist. I just want to confirm this is case.
it turns out that whether or not the imported third party library is on the JRE Class While List has nothing to do with this error. Dataflow runs on compute engine which is not restricted to the app engine white list. The culprit to my error is due to the introduction of a class member which is not serializable even though the the class itself implements Serializable interface.
Serialization is about the fields in your classes - as this is the process of turning an existing Java object into a sequence of bytes; based on the content of that object.
An import within your Java source code is just a hint for the compiler to understand where names are coming from.
In other words: importing class A within source code for class B doesn't necessarily mean that class A will be serialized. You need to have a field of type A within B for that part!
We faced a multi-threading problem when a developer introduced mutability to a Spring Component. Something like this:
#Component //singleton
public class MyComponent {
...
private String intermediateResults;
public String businessMethod() {
... fills in intermediateResults;
}
public String thisGetterShouldNotBeHere() {
return intermediateResults;
}
}
which led to bug with multithreading - the field intermediateResults has been accessed from different threads.
Is there are a way to prevent adding state to a Spring Singleton e.g. by some kind of static analyzer?
SonarQube plugins? Eclipse plugins?
Thanks for suggestions.
MutabilityDetector seems able to do exactly what you need:
Mutability Detector is designed to analyse Java classes and report on whether instances of a given class are immutable. It can be used:
In a unit test, with an assertion like assertImmutable(MyClass.class). Is your class actually immutable? What about after that change you just made?
As a FindBugs plugin. Those classes you annotated with #Immutable, are they actually?
At runtime. Does your API require being given immutable objects?
From the command line. Do you want to quickly run Mutability Detector over an entire code base?
I would anyway advise to add a clear contract stating that the class is supposed to be immutable either via javadoc or via #Immutable annotation on the class itself, to allow (sensible) developers to maintain the class requisites. (In case Mutability Detector fails to detect specific types of immutability eg: Are String, Date really immutable?)
You could implement your own rules with any static analyzer (Like FindBugs, PMD and Checkstyle) to check that your class:
Only allows final properties
Extends a given class
Is final
Uses constructor dependency injection
However, as far as I know, there's no tool specifically configured out of the box for that.
Alternatively you could create an #Immutable annotation and implement the checks there.
Only for example lets consider the class ClassFileAssembler from the sun.reflect package.
This class is a package local class:
class ClassFileAssembler implements sun.reflect.ClassFileConstants {...
So we can not use even its name ClassFileAssembler, we can not import it directly - it will lead to a compiler error.
However we can create a package named sun.reflect in our project and use the ClassFileAssembler name internally in this package - Java compiler will think that we are inside the ClassFileAssembler's package.
If so, why not to try to get a reference to a class object, i.e. ClassFileAssembler.class?
Class<ClassFileAssembler> classFileAssemblerClass = ClassFileAssembler.class;
Unexpectedly this code leads to a run-time error: java.lang.IllegalAccessError: tried to access class sun.reflect.ClassFileAssembler from class sun.reflect.Test.
However we still able to get the ClassFileAssembler class object:
Class<ClassFileAssembler> aClass = (Class<ClassFileAssembler>)Class.forName("sun.reflect.ClassFileAssembler");
It works fine and gives us a full class description.
So, the questions are:
1) What is the difference between techniques, how Class.forName0 retrieves reference to class object, and how .class does it?
2) Why do they have such different security checks?
3) What's the reason to protect .class reference in such way?
4) Do these techniques use different class loaders?
Class.forName don't care about whether a class is package local or not. It is when you attempt to use that class that access is checked. BTW if you do setAccessible(true) you can by pass these access restrictions.
The Reflection library allows you to do many things you cannot do in Java code. The Java has rules as to what you can and cannot do. e.g. you cannot set a final field outside a constructor or more than once. Note: the JVM doesn't have this restriction and at runtime you can use reflections to change it.
The reason this class is package local is to restrict access of the class to code outside this package. This doesn't mean you cannot access it if you really try, but it is less likely you will access it without serious thought being put into it. e.g. when I import classes in my IDE it often suggests classes from com.sun.* which are unlikely to be the right choice. (MY IDE can be set up to ignore these, but I often seem for find some new package I don't want)
The reason Reflections can do this is to support functionality such a Serialization. With Serialization you need to be able to serialize class outside the package of the Serialization library and obtain fields and reset them when deserializing. Reflections is also used by many Inversion of Control libraries though I suspect this is not what they had in mind when they design it.
If you check the javadoc of Class#forName, you will see that:
Note that this method does not check whether the requested class is accessible to its caller.
there is no difference. but you cannot access the static field .class of the package private (no modifier) class ClassFileAssembler.
everyone could access the Class instances, but the fields are protected.
in fact no one designed to protect .class reference this way, it's side effect of protecting other fields.
i dont think so.
I have the following problem, I am wondering whether anyone knows a solution:
I would like to dynamically generate specially named getters for every private field in every subclass of a certain class using aspectj or some other similar bytecode manipulation tool.
I would like the names of the getters to be based on the corresponding field names, but I can settle for having one method taking a field name string and returning a value, as long as there is no reflection involved.
Have you looked into Lombok? If you have access to the source and are just trying to save typing, than its #Data annotation might be what you looking for.
As in Matt's answer, I suggest you Lombok.
Using the #Getter, #Setter annotations on the class level, corresponding getters/setters based on names of all the non-static fields will be generated at compilation.
Much better than annotating classes by hand is to use static crosscutting of AspectJ (page in the official documentation) to add those annotations globally.
Example for declaring #Getter and #Setter on each persistent Entity :
import javax.persistence.Entity;
import lombok.Getter;
import lombok.Setter;
public aspect EntityAspect {
declare #type: #Entity * : #Getter;
declare #type: #Entity * : #Setter;
}
It requires you either to have the source code, or to use compilation by aspectj on existing jar (instrumentation of an existing library).
I'm using java 6 annotation processing api. I have followed the following excellent tutorial for creating an annotation processor that displays a message at build-time:
http://kerebus.com/2011/02/using-java-6-processors-in-eclipse/
However, in my case, I have a simple class as such:
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(value = ElementType.METHOD)
public #interface Criteria {
String id();
double width();
double height();
}
As you can see, the aforementioned annotation is made available to the JVM at runtime using the meta-annotation 'Retention'. I use this 'Criteria' annotation in the source code of another class to annotate a method, like so:
#Criteria(id = "fooBar",
width = 22,
height = 10
)
public void fooStream() {
System.out.println("foo stream method");
}
At runtime, I want to include the 'fooStream' method in another class, ONLY if variables that are passed in match the values of the elements in the #Criteria annotation, namely 'width' and 'height'. My question is, how could I take the method 'fooStream' and inject this into another class at run-time? Is this even possible? I'm not looking for any code examples, just answers to the two aforementioned questions. Also, in the link at the top, there is an example of generating a code using 'JavaFileObject' and 'Writer' instances, where the generated code is passed as a string.
I don't believe Java supports runtime type mutation, meaning to modify the members on a given class you'd have to drop back to a compile time preprocessor or to a bytecode modification scheme.
I'd be able to point you in a better direction if I understood the "why" behind this question, but in the mean time, dynamic proxy classes might get you to where you want to be (JavaWorld article).
From the documentation:
A dynamic proxy class is a class that
implements a list of interfaces
specified at runtime such that a
method invocation through one of the
interfaces on an instance of the class
will be encoded and dispatched to
another object through a uniform
interface. Thus, a dynamic proxy class
can be used to create a type-safe
proxy object for a list of interfaces
without requiring pre-generation of
the proxy class, such as with
compile-time tools. Method invocations
on an instance of a dynamic proxy
class are dispatched to a single
method in the instance's invocation
handler, and they are encoded with a
java.lang.reflect.Method object
identifying the method that was
invoked and an array of type Object
containing the arguments.
Here's a decent tutorial on using Spring to inject dynamic proxies based on custom annotations. I think this is probably closest to the behavior you're after.
If you want runtime modification of you classes, you can use your own classloader and intercept loading of classes, introspect what you want and generate new bytecode using asm library instead of original classes. It is not very tricky, but you must be sure you need exactly that.