The following is a hypothetical problem. I'm purely interested if the effect is SOMEHOW achievable, by any obscure means imaginable (unsafe API, JNI, ASM etc). It is not an XY problem and I don't ever plan to write code like that! I'm just curious about internals.
Let's assume that we have this very simple hierarchy in Java:
class Cupcake {
public String kind;
// ...
}
class WholeRealityItself extends Cupcake {
public Object[] wholeMatterOfUniverse;
// transform internal state because reasons
public performBigBangAndFluctuateACupcake() {
// ... chaotic spacetime fluctuations produce a cupcake
this.kind = "quantum_with_sprinkles";
}
}
Our process is as follows:
WholeRealityItself reality = new WholeRealityItself();
reality.performBigBangAndFluctuateACupcake();
Cupcake cupcake = (Cupcake) reality; // upcast
// from now on the object will be only accessed via it's supertype and never downcast
Putting it into words:
We create an object of subtype, that has a lot of memory allocated.
We perform some internal state transformation on this subtype object.
We upcast the object to it's supertype and from now on we will ONLY refer to it by it's supertype and never downcast
So now our JVM holds a Cupcake reference to an internal WholeRealityItself object with memory that (the programmer knows) will never again be accessed. Yes, I know that references and actual allocated objects are two different things and upcasts/downcasts make the program just "reinterpret" an object.
Completely ignoring the fact that this abomination of a code is unusable and should be replaced with a sane builder/factory/copy or whatever, just assume for the sake of argument that we want it that way. The point is not how to achieve the same effect but if the following is possible:.
Can you force a narrowing of the actual allocated OBJECT to covert it's internals to a Cupcake from WholeRealityItself and force deallocation of wholeMatterOfUniverse?
AKA - can you SOMEHOW slice an underlying allocated OBJECT? Last questions about object slicing are from ~10 years ago.
AKA - can you SOMEHOW slice an underlying allocated OBJECT?
No you can't.
The object is represented by a heap node. If you did anything to interfere with the size or type (class) of the heap node, you are liable to crash the garbage collector.
I guess, you could use abstraction breaking (nasty!) reflection to identify and assign null to all of the fields added by the subclass. But the problem is that you can't do anything about methods of the superclass that the subclass has overloaded. If those methods refer to any of the fields that you have assigned null to, and something calls them, you have a potentially broken (smashed) object.
My advice: create a brand new Cupcake object using the relevant state from your WholeRealityItself object. It will have a different reference. Deal with that.
This David Wheeler quotation may be relevant ...
"All problems in computer science can be solved by another level of indirection."
Neither upcasts nor downcasts change the object itself - they only influence how the compiler treats the reference to the object.
One example are overriden methods: what method is called depends entirely on the runtime type of the object, not on the reference type that the compiler uses:
class Cupcake {
public String kind;
// ...
public void printMeOut() {
System.out.println("Cupcake");
}
}
class WholeRealityItself extends Cupcake {
public Object[] wholeMatterOfUniverse;
#Override
public void printMeOut() {
System.out.println("WholeRealityItself");
}
public performBigBangAndFluctuateACupcake() {
//...
}
}
After your sample code
WholeRealityItself reality = new WholeRealityItself();
reality.performBigBangAndFluctuateACupcake();
Cupcake cupcake = (Cupcake) reality; // upcast
// from now on the object will be only accessed via it's supertype and never downcast
the call cupcake.printMeOut(); will print out "WholeRealityItself" every time now matter how much time passed since the upcast.
You are talking about upcasting and nothing happens to your object. Only way to free would be to have a constructor in cupecake that would take another cupecake as input and would only use the needed parts. After you would release wholeworld.
Related
I'm trying to get to learn more about the JVM when it comes to optimising my code and was curious whether (or more specifically in which ways) it optimises out unused fields?
I assume that if you have a field within a class that is never written too or read from, when the code is run this field will not exist within the class. Say you had a class that looked like this:
public class Foo {
public final int A;
public final float B;
private final long[] C = new long[512];
}
and you only used variables A and B, then you can probably see how initiating, maintaining and freeing variable C is a waste of time for what is essentially garbage data. Firstly would I be correct in assuming the JVM would spot this?
Now my second and more important example is whether the JVM takes inheritance into consideration here? Say for example Foo looked more like this:
public class Foo {
public final int A;
public final float B;
private final long[] C = new long[512];
public long get(int i) {
return C[i];
}
}
then I assume that this class would be stored somewhere in memory kinda like:
[ A:4 | B:4 | C:1024 ]
so if I had a second class that looked like this:
public class Bar extends Foo {
public final long D;
#Override public long get(int i) {
return i * D;
}
}
then suddenly this means that field C is never used, so would an instance of Bar in memory look like this:
[ A:4 | B:4 | C:1024 | D:8 ] or [ A:4 | B:4 | D:8 ]
To prove that a field is entirely unused, i.e. not only unused til now but also unused in the future, it is not enough to be private and unused with the declaring class. Fields may also get accessed via Reflection or similar. Frameworks building upon this may even be in a different module, e.g. Serialization is implemented inside the java.base module.
Further, in cases where the garbage collection of objects would be observable, e.g. for classes with nontrivial finalize() methods or weak references pointing to the objects, additional restrictions apply:
JLS §12.6.1., Implementing Finalization
Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.
Another example of this occurs if the values in an object’s fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage. Note that this sort of optimization is only allowed if references are on the stack, not stored in the heap.
This section also gives an example where such optimization would be forbidden:
class Foo {
private final Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
/* finalize outer Foo object */
}
}
}
The specification emphasizes that even being otherwise entirely unused, the inner object must not get finalized before the outer object became unreachable.
This wouldn’t apply to long[] arrays which can’t have a finalizer, but it makes more checks necessary while reducing the versatility of such hypothetical optimization.
Since typical execution environments for Java allow to add new code dynamically, it is impossible to prove that such an optimization will stay unobservable. So the answer is, there is no such optimization that would eliminate an unused field from a class in practice.
There is, however, a special case. The JVM may optimize a particular use case of the class when the object’s entire lifetime is covered by the code the optimizer is looking at. This is checked by Escape Analysis.
When the preconditions are met, Scalar Replacement may be performed which will eliminate the heap allocation and turn the fields into the equivalent of local variables. Once your object has been decomposed into the three variables A, B, and C they are subject to the same optimizations as local variables. So they may end up in CPU registers instead of RAM or get eliminated entirely if they are never read or contain a predictable value.
Not that in this case, you don’t have to worry about the inheritance relation. Since this optimization only applies for a code path spanning the object’s entire lifetime, it includes its allocation, hence, its exact type is known. And all methods operating on the object must have been inlined already.
Since by this point, the outer object doesn’t exist anymore, eliminating the unused inner object also wouldn’t contradict the specification cited above.
So there’s no optimization removing an unused field in general, but for a particular Foo or Bar instance, it may happen. For those cases, even the existence of methods potentially using the field wouldn’t impose a problem, as the optimizer knows at this point, whether they are actually invoked during the object’s lifetime.
I have two classes:
public class Base{
public Derived becomeDerived(){
Derived d = new Derived(this);
//set this pointer pointing to d,
//this = d; doesn't work
return d;
}
}
public class Derived extends Base{
public Derived(Base b){ }
}
Is it possible to change the runtime type of current object by its method as I show in the example?
The reason why I want to do that is providing a method for concatenating objects.
I have
public abstract class Table{
}
and
public class ComplexTable extends Table{ }
which is in fact a linked-list of Table objects.
I would like to provide a method, say Table.append(Table t) which not only modify the current Table object, but also make it ComplexTable's instance.
No.
In your example, Base wouldn't become Derived, it would return a new Derived object.
Base foo = new Base();
foo = foo.becomeDerived();
This is likely what's throwing you off, remember that the variable is not the object, just a reference to one. So while you can say foo changes from Base to Derived, the run-time type of an object didn't change, you made a new object with a different run-time type and reassigned the variable.
Edit: More in depth example. I give the objects "names" just so it's easier to understand.
Base foo = new Base();
/* After execution:
*
* Vars: | Objects:
* foo ----+---> a Base object (Name: Joe)
*/
foo = foo.becomeDerived();
/* After execution:
*
* Vars: | Objects:
* foo ----+---> a Derived object (Name: Phil)
* | a Base object (Name: Joe)(notice nothing references it)
*/
The type of "Joe" did not change. Joe was and will always be a Base object. This is what you're referring to by "run-time type of an object." However, the run-time type of variables change all the time! In this example, foo starts as Base but becomes Derived.
You cannot set this to d as this is super type of Derived d.
But it is possible to store object of type Derived like d in this case into a reference of Type Base.
You can store types of derived classes in reference of base class. But it is not changing types technically just reference holding object of derived type.
Unlike in C++
You can not change or reassign the value of this.
This was chosen to be a reserved word.So Answer is
No ,it is not possible to change the runtime type of current object
.
One more error i could find in your code is always use the Base reference variable so you can refer to objects of classes extending it.
Base b;
b=new Derived();
b=new Base();
Bad idea follows
It is possible to change the type of an object, but it relies on behaviour that is not part of the JVM spec and is thus not portable. You have been warned.
There is a class sun.misc.Unsafe that let's you read/write memory at any offset of an object. The type of an object is stored in the object's header at offset 8 on 64-bit JVMs. Thus, to change the type of the object all you need to do is to change the value at this offset. Note that the types/classes your switching between must have the same structure (reference fields on the same offsets and having the same total size). If not, the garbage collector will read non-references as references (or vice-versa) and crash you JVM.
I'm not providing working example intentionally as I'm not recommending this. Stuff like this is more suitable in C than in Java. It's really not that hard to do though, and the link I've provided together contains all information required.
Some tests I made indicates that it works on several JVMs and that the JIT is robust against these dangerous object type changes. That is no promise that it works in all systems and under all conditions.
By the way, I'm curious to hear from someone who can explain why the JIT doesn't consider the type of an object as a jit-compile-time constant, or how the JIT knows to recompile when the type of an object has changed.
In java, can we pass superclass Object to subclass reference ?
I know that it is a weird question/practically not viable,
but I want to understand the logic behind this
Why is it not allowed in java.
class Employee {
public void met1(){
System.out.println("met1");
}
}
class SalesPerson extends Employee
{
#Override
public void met1(){
System.out.println("new met1");
}
public void met2(){
System.out.println("met2");
}
}
public class ReferenceTest {
public static void main(String[] args) {
SalesPerson sales = new Employee(); // line 1
sales.met1(); // line 2
sales.met2(); // line 3
}
}
What would have happened if Java allowed compilation of line 1?
Where would the problem arise?
Any inputs/link are welcomes.
If your SalesPerson sales = new Employee(); statement was allowed to compile, this would have broken the principles of Polymorphism, which is one of the features that the language has.
Also, you should get familiar with that does compile time type and runtime type mean:
The compile-time type of a variable is the type it is declared as, while the runtime type is the type of the actual object the variable points to. For example:
Employee sales = new SalesPerson();
The compile-time type of sales is Employee, and the runtime type will be SalesPerson.
The compile-time type defines which methods can be called, while the runtime type defines what happens during the actual call.
Let's suppose for a moment that this statement was valid:
SalesPerson sales = new Employee();
As I said, the compile-time type defines which methods can be called, so met2() would have been eligible for calling. Meanwhile, the Employee class doesn't have a met2() and so the actual call would have been impossible.
No. It makes zero sense to allow that.
The reason is because subclasses generally define additional behavior. If you could assign a superclass object to a subclass reference, you would run into problems at runtime when you try to access class members that don't actually exist.
For example, if this were allowed:
String s = new Object();
You would run into some pretty bad problems. What happens if you try to call a String method? Would the runtime crash? Or perhaps a no-op would be performed? Should this even compile?
If the runtime were to crash, you could use runtime checks to make sure the objects you receive will actually contain the methods you want. But then you're basically implementing guarantees that the Java type system already provides at compile-time. So really that "feature" cost you nothing but a bunch of type-checking code that you shouldn't have had to write in the first place.
If no-ops were executed instead of nonexistent methods, it would be extremely difficult to ensure that your programs would run as written when the members you want to access don't exist, as any reference could really be an Object at any point. This might be easy to handle when you are working on your own and control all your code, but when you have to deal with other code those guarantees essentially vanish.
If you want the compiler to do the checking, assuming compiler writers don't hunt you down and give you a stern talking-to -- well, you're back to "normal" behavior once more. So again, it's just a lot of work for zero benefit.
Long story short: No, it's not allowed, because it makes zero sense to do so, and if a language designer tried to allow that they would be locked up before they could do any more harm.
If you inherit from a class, you always specialize the common behavior of the super class.
In your example, the SalesPerson is a special Employee. It inherits all behavior from the super class and can override behavior to make it different or add new behavior.
If you, as it is allowed, initialize a variable of the super type with an instance of the sub type like Employee e = new SalesPerson(), then you can use all common behavior on that variable.
If instead, you were possible to do the other way round, there might be several uninitialized members in the class.
You find this very often when using the Java Collection API, where for example you can use the common List class on operations like iterating through it, but when initializing it, you use for example the sub class ArrayList.
I'm learning Scala at the moment and I came across this statement in Odersky's Programming Scala 2nd edition:
one way in which Scala is more object-orientated than Java is that classes in Scala cannot have static members.
I'm not sufficiently experienced in either Java or Scala to understand that comparison. Why does having static members make a language less OO?
Odersky's statement is valid and significant, but some people don't understand what he meant.
Let's say that in Java you have a class Foo with method f:
class Foo {
int f() { /* does something great */ }
}
You can write a method that takes a Foo and invokes f on it:
void g(Foo foo) { foo.f(); }
Perhaps there is a class SubFoo that extends Foo; g works on that too. There can be a whole set of classes, related by inheritance or by an interface, which share the fact that they can be used with g.
Now let's make that f method static:
class Foo {
static int f() { /* does something great */ }
}
Can we use this new Foo with g, perhaps like so?
g(Foo); // No, this is nonsense.
Darn. OK, let's change the signature of g so that we can pass Foo to it and have it invoke f.
Ooops -- we can't. We can't pass around a reference to Foo because Foo is not an instance of some class. Some people commenting here are confused by the fact that there is a Class object corresponding to Foo, but as Sotirios tried to explain, that Class object does not have an f method and Foo is not an instance of that class. Foo is not an instance of anything; it is not an object at all. The Class object for Foo is an instance of class Class that has information about Foo (think of it as Foo's internal Wikipedia page), and is completely irrelevant to the discussion. The Wikipedia page for "tiger" is not a tiger.
In Java, "primitives" like 3 and 'x' are not objects. They are objects in Scala. For performance your program will use JVM primitives for 3 and 'x' wherever possible during execution, but at the level you code in they really are objects. The fact that they are not objects in Java has rather unfortunate consequences for anyone trying to write code that handles all data types -- you have to have special logic and additional methods to cover primitives. If you've ever seen or written that kind of code, you know that it's awful. Odersky's statement is not "purism"; far from it.
In Scala there is no piece of runtime data that is not an object, and there is no thing you can invoke methods on that is not an object. In Java neither of these statements in true; Java is a partially object-oriented language. In Java there are things which are not objects and there are methods which aren't on objects.
Newcomers to Scala often think of object Foo as some weird replacement for Java statics, but that's something you need to get past quickly. Instead think of Java's static methods as a non-OO wart and Scala's object Foo { ... } as something along these lines:
class SomeHiddenClass { ... }
val Foo = new SomeHiddenClass // the only instance of it
Here Foo is a value, not a type, and it really is an object. It can be passed to a method. It can extend some other class. For example:
abstract class AbFoo { def f:Int }
object Foo extends AbFoo { def f = 2 }
Now, finally, you can say
g(Foo)
It is true that a "companion object" for a class is a good place to put non-instance methods and data for the class. But that companion object is an object, so the usual rules and capabilities apply.
The fact that in Java you put such methods on non-objects -- limiting how they can be used -- is a liability, not a feature. It is certainly not OO.
I am not sure I completely buy that argument, but here is one possible reasoning.
To an object-oriented purist, everything should be an object, and all state should be encapsulated by objects. Any static member of a class is by definition state which exists outside of an object, because you can use it and manipulate it without instantiating an object. Thus, the lack of static class members makes for a more pure object-oriented language.
Well, with static members like methods you don't have any objects to create and nevertheless you can call such static methods. You only need the static classname in order to set the namespace for these methods, for example:
long timeNow = System.currentTimeMillis(); // no object creation
This rather gives a feeling like in procedural languages.
static members belongs to the Class not to the object while the main concept of oop lies among the relation between the individual objects of dirrefer Class.
A static method in Java is one that operates on the class itself, and doesn't need an Object to be created first. For example, this line:
int c = Integer.parseInt("5");
Integer.parseInt() is static because I didn't have to go Integer i = new Integer(); before using it; this isn't operating on any particular object that I've created, since it's always going to be the same, and is more like a typical procedural function call instead of an object-oriented method. It's more object-oriented if I have to create an object for every call and we encapsulate everything that way instead of allowing static to use methods as faux-procedural-functions.
There are several competing definitions of what exactly object-orientation means. However, there is one thing they all can agree on: dynamic dispatch is a fundamental part of the definition of OO.
Static methods are static (duh), not dynamic, ergo they are by definition not object-oriented.
And logically, a language that has a feature which isn't object-oriented is in some sense "less OO" than a language which doesn't have said feature.
To make a class immutable what I can do is:
1)Make class final
2)do not provide setters
3)mark all variables as final
But if my class has another object of some other class then , somone can change value of that object
class MyClass{
final int a;
final OtherClass other
MyClass(int a ,OtherClass other){
this.a = a;
this.other = other;
}
int getA(){
return a;
}
OtherClass getOther(){
return other;
}
public static void main(String ags[]){
MyClass m = new Myclass(1,new OtherClass);
Other o = m.getOther();
o.setSomething(xyz) ; //This is the problem ,How to prevent this?
}
}
A) Make the OtherClass immutable as well
or
B) Don't allow direct access to the OtherClass object, instead providing only getters to act as a proxy.
Edit to add: You could make a deep copy of OtherClass and return a copy rather than the original, but that generally isn't the type of behavior you would expect in Java.
Immutability is best considered from the perspective of the API user. So your object API needs to satisfy the following two conditions:
No way for an external user to change the value of the object
A guarantee that any time the user reads or makes use of the object's value in the future, it will get the same result
Important note: It is in fact OK to have mutable data inside an immutable object as long as it behaves as an immutable object from the perspective of the API user. Consider java.lang.String for example: although it is generally considered as the definitive immutable class, it does in fact have a mutable internal field for caching the hashCode (not many people know this!).
So to address your question, if you wish to contain another (mutable) object inside an immutable object then you typically need to do one or more of the following:
Guarantee that nobody else can change the value of the mutable object. Typically this means ensuring that no-one else can have a reference to the mutable object, so this is only usually possible if you create the object yourself rather than accept a reference from outside.
Take a defensive deep copy of the mutable object, and don't hand out references to the new copy. Only allow operations that read the new copy in the public API. If you need to hand out a reference to this object, then you need to take another defensive copy (to avoid handing out a reference to the internal copy).
Use an immutable wrapper for the mutable object. Something like Collections.unmodifiableList. This is useful if you want to hand out a reference to the internal mutable object but don't want to run the risk of it being modified.
All of these solutions are a bit hacky - a better solution overall is to avoid the use of mutable objects within immutable objects. In the long run it's asking for trouble because sooner or later a mutable reference will leak out and you will have an extremely hard to find bug. You are better moving towards a full hierarchy of immutable objects (the approach taken by languages like Scala and Clojure)
I assume OtherClass (by the way you say Other once) is meant to be a class you don't control, or which has to have a setter.
If you can't remove getOther, change it to getOtherView and return a read-only view of other. There will be wrappers for all the get methods, but no set ones.
Return deep clones from your getters. You may find this to be no easy task.
All the objects referenced in the immutable class should be immutable, or at least be encapsulated as private and making sure that they are not modified (not inside the methods of your class and definitely not from the outside). For instance, if you have this situation:
public class MyImmutable {
private MutableClass mutableObject;
}
... You can not provide the getMutableObject() method, because doing so will open the door for outside modifications, like this:
myImmutable.getMutableObject().setSomeAttribute(newValue);
As a special case of the above, all collections and/or maps should be made immutable, with the ummodifiableXXX() methods in the Collections class.
you cannot (reasonably) stop that in java. if you don't have control over the other class, there are ways to effectively get immutable behavior, but it can be very expensive in practice. basically, you must always return a copy of that class in any public method return values. (the jdk actually has this problem with the TimeZone class).
But If my class has another object of some other class then , somone
can change value of that object...
Java objects are not primitive. If you mark a primitive as final, then its value cannot be changed once it is assigned. However, object contents cannot be final, only object references can be final. So you cannot make an object in this way.
One solution might be abandoning all setter/mutator methods those could change the particular fields of the object and encapsulating them in a way that you can only access them, not change them.
It is possible to create the immutable class in java by following ways
1.Don't Provide setter methods.
2.Make all fields are as final and private.
3.Make Class as final.