UGRC - Report - Niraj Kumar-1
UGRC - Report - Niraj Kumar-1
Niraj Kumar
BT19CS031
[email protected]
Report Submitted to
National Institute of Technology Mizoram
of
Bachelor of Technology
by
2
APPROVAL SHEET
This report entitled “Value Types in Java and their Interning” by Niraj Kumar is
approved for the degree of Bachelor of Technology in Computer Science &
Engineering.
SUPERVISOR
________________
________________
HEAD OF DEPARTMENT
________________
________________
Date : ___________
Place : ___________
3
DECLARATION
I declare that this written submission represents my own words and wherever others’
ideas or words have been included, I have adequately cited and referenced the original
sources. I also declare that I have adhered to all principles of academic honesty and
integrity and have not misrepresented or falsified or fabricated any idea/data/source
in my submission. I understand that any violation of the above will be cause for
disciplinary action by the institute and can also evoke penal action from the sources
which have not been properly cited or from whom proper permission has not been
taken.
______________
(Signature)
______________
(Name of the student)
______________
(Enrollment No.)
Date :
Place:
4
CERTIFICATE
It is certified that the work contained in the report titled “Value Types in Java and
their Interning” by Niraj Kumar (Enrollment No: BT19CS031), has been carried
out under my supervision for 7 and 8 semester Project Phase-I and II.
th th
5
ACKNOWLEDGEMENTS
I am grateful and would like to express my sincere gratitude to Dr. Sandeep Kumar
Dash and Prof. V Krishna Nandivada for giving me the opportunity to work under
his supervision and his expert guidance and continuous encouragement throughout the
course of the project to see that this project finds its target since its commencement to
its completion.
Furthermore, I would like to acknowledge Eclipse IDE and Visual Stdio for
providing the necessary platform for evaluation.
I would like to express the deepest appreciation towards Dr. Sandeep Kumar Dash,
Head of the Department of Computer Science and Engineering, NIT Mizoram
and Prof. V Krishna Nandivada, Head of the Department of Computer Science
and Engineering, IIT Madras whose invaluable guidance supported us in
completing this project. Also, I would like to acknowledge the Department of
Computer Science and Engineering, National Institute of Technology, Mizoram
and Department of Computer Science and Engineering, Indian Institute of
Technology, Mizoram for providing infrastructural facilities in order to facilitate
research on this task.
At last I must express sincere heartfelt gratitude to all the professors and staff members
of the Department of Computer Science and Engineering, my friends who helped
me directly or indirectly during this course of the project work.
6
ABSTRACT
One of the important optimizations enabled by the introduction of value types (JEPs 401 and
402) is that objects of such value types can be flattened (or "inlined") into enclosing objects
(called "containers"). Thus, instead of storing a reference to the object as part of the container,
various fields of the object can themselves be flattened and kept in the container, to form an
expanded object.
This reduces the access time of the flattened objects, however, it may incur additional costs
because of the increased container size. One of the possible ways to improve the performance
of Java applications would be to identify value-objects that can be “interned” and the derive
the benefits. We would like to identify value-objects that can be interned and intern those
objects that are beneficial to intern.
7
CONTENT
Page no.
1. Approval Sheet 3
2. Declaration 4
3. Certificate 5
4. Acknowledgements 6
5. Abstract 7
6. Content 8
7. Introduction 9
8. Work done during Project
a. Background Study 10
b. Motivation for Object interning 11
c. Procedure for Object interning 12
8
Introduction
So, Java already has value types – the primitive types (byte, short, int. long, float,double,
char and boolean).
Because some types naturally behave like values, and you would like to avoid the overhead
that is necessary for objects. For example a java.util.Date is just a timestamp value
(a long containing a number of milliseconds since 01-01-1970, 00:00:00 GMT). You’re
normally only interested in the value that a Date object contains, and not in the identity of the
object.
Value types do not necessarily contain just a single value. For example a type that represents
complex numbers would contain two values, for the real and imaginary part of the number.
You’d want to store this as two double values that are treated as a unit.
In State of the Values – Infant Edition, a number of use cases for value types are listed:
▪ Numeric types, for example complex numbers, extended-precision or unsigned
integers and decimal types
▪ Native types for which there is no equivalent Java primitive type
▪ Algebraic data types, for example Optional<T> shouldn’t need to be an object itself
▪ Tuples
▪ Cursors (for example iterators)
▪ Flattening (avoid unnecessary pointer indirections)
9
Work done during Project
1. Background Study
This paper, explain value types: what they are, why it would be beneficial to have
them in Java and an introduction to what is involved in adding them to Java.
Finally, we’ll have a quick look and comparison with value types available in
Scala.
This JEP introduces primitive classes, special kinds of value classes that define new
primitive types. The Java programming language will be enhanced to recognize
primitive class declarations and support new primitive types in its type system. The
Java Virtual Machine will be enhanced with a new Q carrier type to encode declared
primitive types.
Repurpose the primitive wrapper classes to act as declarations for the basic
primitives (int, double, etc.), unifying the treatment of these types with that of other
types declared by primitive classes. This is a preview language and VM feature.
10
E. Few Websites used for Studying Java String and intern() method –
geeksforgeeks.org
Thorough integration of values into the JVM can support a number of language
features which may be desirable additions to the Java language, or features already
implemented sub optimally by other JVM languages. Some examples include:
• Numerics
The JVM offers exactly eight efficient numeric types like complex numbers, extended-
precision or unsigned integers, and decimal types are widely useful but can only be
approximated (to the detriment of type safety and/or performance) by primitives or object
classes.
• Native types
Modern processors support a wide variety of native data types, and (as with numerics)
only a few of them map directly to Java primitives. This makes it difficult or impossible
to write Java code which compiles directly to (for example) vector instructions.
• Tuples
A tuple of values should itself be regarded as a value, and should not need an Object box.
(Even if the language does not support tuples in its type system, many languages support
multi-valued return, which is a special sub-case of tuples.)
11
• Cursors
An iterator or other cursor into a complex data structure should not require
an Object box. Moreover, it should be possible for clients of data structures (managed
and/or native) to pass around iterators and other “smart pointers” into the data structures
with full encapsulation and typesafety.
• Flattening
Values provide a natural way to express data structures with fewer pointer indirections.
Although value types are not designed as a general mechanism for layout control, using
them will permit JVMs to arrange some data structures more efficiently
The idea that we have come upon to mimic a kind of object interning and its benefits is
by making use of Hashmap data structure, overriding Objects.equals() &
Objects.hashcode() and changing the way in which Object is created for the class which
is supposed to get interned.
➢ We need to override equals() and hashcode() method in our class. The hashcode()
will return unique hashvalue for objects with different set of fields value. And for
same set of field value it should return the same value.
Now we need to override equals() methods such that it returns true when two objects
are same and false when two objects are different. For this we simply compare the
references instead of comparing field values one by one. We guarantee in our
implementation that two objects have same references when they are same otherwise
they are different.
Two Objects are said to be same when each of corresponding fields between them are
same.
12
➢ We introduce a static Hashmap variable in the class which will work like Object
Constant pool.
This Hashmap will store integer as an index and Object reference as value.
We make use of property of Hashmap like constant time insertion, deletion and
searching.
The index is obtained from Objects.hash() method and if that index is not present we
add that index with value as newly created Object reference, otherwise we return the
corresponding Object reference stored as value inside map.
➢ We avoid the use of new operator to create object of the class. Instead we introduce a
static method create_object() which takes parameter as the initial field value .
This function now creates and returns the Object reference if is not present in the
constant pool otherwise return the already present Object reference.
So to implement this we have restricted our constructor to be private.
Discussing a situation where we can intern an object and get the additional benefits in terms
of code complexity and space optimisation.
Considering a situation, there is a list of people residing in a state. We want to create objects
representing them and further we will perform some operations over them.
So the structure of the Object is in the way that there is a one class named Userdetails
containing user name, user id and demographics detail from where he belongs like city name
and pincode.
This city name and pincode is added to Userdetails using another Object of a class named
Demographics. This Demographics class stores that information.
13
Explaining why we have created Demographics class for storing
pincode and city name instead of directly appending them to Userdetails
class as a two separate variable.
If we look at a practical situation, for any State in India there are only limited number of
combinations of city name and pincode for e.g., in Madhya Pradesh the total no. of available
pincode is 8311 but population is 8 crores.
So, the point is that there exist only limited number of Demographics but those details are
shared by large amount of population.
So instead of creating a separate field of these things for every individual we can actually
create one object for every possible Demographics and let them be shared among various users.
Each user will have a single separate reference copy to this Demographics Object. Hence it
reduces the number of fields inside the Userdetails Objects.
And because this Demographics object inside Userdetails class is a mutable object so we
can’t allow user to share the original reference because if in future one user changes its
Demographics details then actually my original Demographic object will be hampered and
other users using the old Demographics information will loose their values.
import java.io.*;
import java.util.*;
class Demographics
{
String city;
int pincode;
@Override
public String toString()
{
return ",City : "+this.city+" ,Pincode : "+this.pincode;
}
}
class Userdetails
{
String name;
int userid;
Demographics d;
@Override
public String toString()
{
15
return "Userid : "+userid+" ,Name : "+name+" "+d.toString();
}
}
class UGRC_code_1
{
public static void main(String [] args)
{
Demographics d1=new Demographics("Bhopal",123456);
Demographics d2=new Demographics("Indore",123457);
System.out.println(u1);
System.out.println(u2);
System.out.println(u3);
System.out.println(u4);
}
}
OUTPUT
16
So, the advantage we get by creating a Demographics object instead of inlining the fields
inside the Userdetails, only once we create the object d1 and d2 and that is being shared by 4
users. If this is not taken into care then while creating each user, separately we need to pass
every Demographics field to the constructor argument which is repetitive.
➢ To compare if the two different users have same or different Demographics, we make use
of equals(). We need to override this method from Object class in such a way that for every
two unique object we return false otherwise true.
But the overhead is. we are doing each field comparison which again is costly, because
the equals() is a very frequent operation. So, this also needs to be optimised.
Now after analysing the code, we come at a conclusion that if we intern every
Demographics class object, we derive many benefits.
Discussing the logic behind how this interning is done from code point of view.
We have a HashMap which stores all the references of my Demographics objects for every
unique Demographics.
Now user cannot create object using new keyword. We have a special static method called
create_object which handles the creation of my objects. It creates new object for every unique
combination of city and pincode otherwise it returns the already created object reference from
the HashMap.
Here the HashMap can be looked as Object constant pool similar to String constant pool.
17
Presented Algorithm for Interning
7. This way we create a single object that shares its multiple reference and
the object is made immutable. Interning thus helps is object comparison and
eliminating duplicates thus saving time and space.
8. Output – Modified program with the objects of the selected class
interned.
18
//After Modification and Interning
import java.io.*;
import java.util.*;
class Demographics
{
String city;
int pincode;
map.put(hashvalue,new_obj);
return new_obj;
}
return obj;
}
19
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
return false;
}
@Override
public String toString()
{
return ",City : "+this.city+" ,Pincode : "+this.pincode;
}
@Override
public int hashCode()
{
return Objects.hash(this.city,this.pincode);
}
}
class Userdetails
{
String name;
int userid;
Demographics d;
@Override
Public String toString()
{
return "Userid : "+userid+" ,Name : "+name+" "+d.toString();
}
class UGRC_code_2
{
public static void main(String [] args)
{
Demographics d1=Demographics.create_object("Bhopal",123456);
Demographics d2=Demographics.create_object("Indore",123457);
System.out.println(u1+"\n"+u2+"\n"+u3+"\n"+u4);
21
u1.update(123466);
u2.update(123458,"Indore");
System.out.println("\n\n"+u1+"\n"+u2+"\n"+u3+"\n"+u4);
}
}
OUTPUT
22
Analysis using Soot Framework
A sample piece of code inside Soot Framwork, which takes our code and sends us the basic
details about number of classes and methods inside them.
1. Driver.java
2. PointsToAnalysis.java
3. UGRC_code_1.java
//Driver.java
package cs6235.a1;
import java.util.Arrays;
import cs6235.a1.submission.PointsToAnalysis;
import soot.PackManager;
import soot.Transform;
public class Driver
{
public static void main (String [] args)
{
String classPath = "tests";
String queriesPath = "q.txt";
String mainClass = "UGRC_code_1"; // Name of ur main class
that u want to analyse
if(args != null && args.length > 0)
{
int i = 0;
while(true)
{
if(args[i].equals("-cp"))
23
{
classPath = args[i+1];
i += 2;
}
else if (args[i].equals("-mainClass"))
{
mainClass = args[i + 1];
i += 2;
}
else if (args[i].equals("-qp"))
{
queriesPath = args[i + 1];
i += 2;
}
Options.queriesPath = queriesPath;
String [] sootArgs =
{
"-v","-cp", classPath,"-pp","-w", "-app","-src-prec",
"java","-p", "cg.cha", "enabled:true","-p", "cg.spark",
"enabled:false","-f", "J",
//"-d", "output",mainClass
};
PackManager.v().getPack("wjtp").add(new
Transform("wjtp.pta", pta));
soot.Main.main(sootArgs);
}
}
//PointsToAnalysis.java
package cs6235.a1.submission;
import java.util.Iterator;
import java.util.*;
import java.util.Map;
import cs6235.a1.AnalysisBase;
import soot.*;
import soot.Scene;
import soot.SootClass;
import soot.JastAddJ.List;
import soot.util.Chain;
import soot.Type;
25
public String getResultString()
{
// TODO Auto-generated method stub
return null;
}
@Override
protected void internalTransform(String phaseName,
Map<String, String> options)
{
// TODO Auto-generated method stub
// **
while(it.hasNext())
{
SootClass sc = it.next();
String str=""+sc.getName();
if(!str.contains("jdk"))
System.out.println(sc.getFieldCount()+" - "+str);
SootMethod m =
Scene.v().getSootClass("Demographics").getMethodByName("eq
uals");
Body b = m.getActiveBody();
//UnitGraph g = new BriefUnitGraph(b);
}
26
// UGRC_code_1.java
import java.io.*;
import java.util.*;
class Demographics
{
String city;
int pincode;
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null) return false;
if (this.getClass() != o.getClass()) return false;
Demographics other = (Demographics)o;
return other.pincode==this.pincode &&
other.city.equals(this.city);
}
@Override
public String toString()
{
return ",City : "+this.city+" ,Pincode : "+this.pincode;
}
}
27
class Userdetails
{
String name;
int userid;
Demographics d;
@Override
public String toString()
{
return "Userid : "+userid+" ,Name : "+name+"
"+d.toString();
}
}
class UGRC_code_1
{
public static void main(String [] args)
{
Demographics d1=new Demographics("Bhopal",123456);
Demographics d2=new Demographics("Indore",123457);
System.out.println(u1);
System.out.println(u2);
System.out.println(u3);
28
System.out.println(u4);
}
}
OUTPUT
29
Highlighting advantages
➢ After interning the Demographics object, we can share this object among other users without
having a separate reference copy. And if in future user try to modify its demographics, it
will not hamper the original object.
Because inside Object constant pool Demographics object behaves as immutable and when
user tries to update the value, a fresh object is created inside pool and returned back. And if
the updated demographics is already present inside pool, we return that reference only hence
saving the pool from duplicate entry.
This saves lot of Heap memory and also protects the fields from being modified.
➢ Another advantage is with equals() method. Before interning if we wanted to compare the
demographics of two people, we implemented the equals() method in such a way that is
compares each field one by one which is a very time taking process.
After interning we directly compare the reference of Demographic object. Hence with single
comparison we can achieve the desired output.
So, these are some major advantages of Object interning which gives us good benefit.
30
Conclusion
All the consequences of having value types in Java are not yet clear (the point of Project Valhalla
is to experiment with them and discover what exactly it would mean). As mentioned in State of
the Values, for value types you should be able to say:
▪ We can compare them with ==, just like the existing primitive types.
▪ Since they are not references, you can’t set a variable of a value type to null.
▪ All reference types implicitly inherit from class java.lang.Object. This should probably
not be true for value types, because the facilities that class Object provides don’t make
sense for value types (for example, because values have no object identity it makes no
sense to lock on a value, and clone() and finalize() would also not be useful).
▪ There will need to be some way to box value types using a wrapper type that is a reference
type, just like we have wrapper classes to box the built-in primitive types.
▪ There will be limitations to inheritance, because without any room to store runtime type
information in the value it’s hard to have polymorphism. Maybe it won’t be possible at
all to extend value types. If you have a variable of value type A and you assign it a
value that is of value type B extends A, then there’s no way for the JVM to know at
runtime that the variable actually refers to a value of type B.
That’s just the beginning. State of the Values goes into much more detail and also lists some
open questions, and some ideas about how it would be implemented in a JVM.
Once this has all has been thought through, then there’s the question of backward compatibility.
There are a number of classes in the standard library which would be a natural fit for value
types, such as class java.util.Date that I already mentioned. However, it will be impossible to
change these existing classes into value types without breaking backward compatibility. Should
new value types be added for those classes, for example a type DateValue – and then everybody
would have to learn to use the new value types, and ignore the old reference types that won’t be
removed because of backward compatibility reasons? That wouldn’t make the language easier
to use.
31
Future Work
(Soot is a product of the Sable research group from McGill University, whose objective is to
provide tools leading to the better understanding and faster execution of Java programs.
Originally, Soot started off as a Java optimization framework. By now, researchers and
practitioners from around the world use Soot to analyze, instrument, optimize and visualize Java
and Android applications)
32
References
1. https://www.developer.com/java/java-valuetype/
2. https://www.jesperdj.com/2015/10/04/project-valhalla-value-types/
3. https://www.javatpoint.com/java-string-intern
4. docs.oracle.com/String
6. stackoverflow.com
7. http://cr.openjdk.java.net/~jrose/values/values-0.html
*******
33