java.lang.instrument.Instrumentation is not giving expected result - java

I am using java.lang.instrument package to get the memory size of java object (can be nested ).
I am using below to get Object Size :
import java.lang.instrument.Instrumentation;
public class ObjectSizeFetcher {
private static Instrumentation instrumentation;
public static void premain(String args, Instrumentation inst) {
instrumentation = inst;
}
public static long getObjectSize(Object o) {
return instrumentation.getObjectSize(o);
}
}
I have Person class having below fields :
private String name ;
private int age;
private Addresses addresses [] ;
Now need size of below person Object :
Person person = new Person();
person.setName("aa");
person.setAge(11);
Addresses addresses [] = new Addresses[2000];
for(int i = 0 ; i < 1000 ; i ++){
addresses[i] = new Addresses();
addresses[i].setAddress1("dadadadafasfasf"+i);
addresses[i].setAddress2("dadadadafasfasfdasdsadsd"+i);
}
person.setAddresses(addresses);
System.out.println("size : " + ObjectSizeFetcher.getObjectSize(person));
Now after executing this, I am getting output as :
size : 24
Issue is If i am iterating this loop 10 times, or 1000 times, or 100000 times, i am getting Size as 24.
I am expected that person object memory size should increase if number of times loop increased as person object is having more addresses.
Why java.lang.instrument.Instrumentation is not giving correct results ?

Simply said: an object consist of it's own fields. But if these fields are objects themselves, they consist simply of the reference to those other objects. So your array is an object, and only the reference to that array is included. The size doesn't contain the whole object tree of what an object exists of, in other words.

Arrays are objects itself and you're declaring only one array.
Addresses addresses [] = new Addresses[2000]; //the single array instance
for(int i = 0 ; i < 1000 ; i ++){
addresses[i] = new Addresses();
addresses[i].setAddress1("dadadadafasfasf"+i);
addresses[i].setAddress2("dadadadafasfasfdasdsadsd"+i);
}
and populate it with address records. So your arrray pointing the same area in memory, it is still the same reference. The only difference made is that you're createing new Addresses instances and fill your memory outside the class in which array addresses[] declared. For further explanation;
Before: addresses[] ----> 0x0000f -> {}
After: addresses[] ----> 0x0000f ->{address1, address2, ..., address1000}
So your reference for addresses[] stays the same, it keeps pointing the same area. It's only the reference and not the array itself.

Related

Using variables instead of a long statement?

I am facing a confusion while working with objects. I searched google but couldn't find actual words to search for. The question is:
I am working with objects which consist some other object. For example:
public void mapObjects(A a, B b) {
a.setWeight(BigDecimal.valueOf(b.getWeight));
//Now my doubt lies here
if (a.getCharges.getDiscounts.getDiscountList != null) {
for(int i = 0; i < a.getCharges.getDiscounts.getDiscountList.size(); i++){
b.getList().get(0).setDiscountValue(a.getCharges.getDiscounts.getDiscountList.get(i).getValue());
b.getList().get(0).setDiscountName(a.getCharges.getDiscounts.getDiscountList.get(i).getValue);
}
}
}
The above code is just an example. The project in which I am working uses similar type of coding style. The usage of a.getCharges.getDiscounts.getDiscountList() kind of code always bugs me. Because I am again and again calling the same statement.
When I asked a senior why dont we save this statement into a simple List<> variable. He told me that it will use extra references which will increase overhead. Can using a variable be that much overhead than calling getters again and again?
As Java exchanges references not actual object, if you take a local variable it will just add a reference variable entry in stack frame.
This memory would be very less, almost negligible
This memory will be released once the method is completed because this will be local to the method
Despite that, you can gain significant performance gains if you use local variables. You are extracting same information within loop multiple times.
a.getCharges.getDiscounts.getDiscountList.size() is called multiple times. It should be a local variable.
b.getList().get(0) is being called multiple times. It should be a local variable.
a.getCharges.getDiscounts.getDiscountList is called multiple times. It should be a local variable.
Changing these to local variables would results in good performance gains, because unnecessary method calls would be saved.
Point your senior to this. If it works for limited resources on Android, I guess the technique of storing in local variables everything used in a for cycle is actually beneficial for performance anywhere.
In the excerpt below, note that we aren't even speaking about the overhead introduced by calling the (virtual) list.size() method, only storing the array.length as a local variable produces notable differences in performance.
public void zero() {
int sum = 0;
for (int i = 0; i < mArray.length; ++i) {
sum += mArray[i].mSplat;
}
}
public void one() {
int sum = 0;
Foo[] localArray = mArray;
int len = localArray.length;
for (int i = 0; i < len; ++i) {
sum += localArray[i].mSplat;
}
}
public void two() {
int sum = 0;
for (Foo a : mArray) {
sum += a.mSplat;
}
}
zero() is slowest, because the JIT can't yet optimize away the cost of getting the array length once for every iteration through the loop.
one() is faster. It pulls everything out into local variables, avoiding the lookups. Only the array length offers a performance benefit.
two() is fastest for devices without a JIT, and indistinguishable from one() for devices with a JIT. It uses the enhanced for loop syntax introduced in version 1.5 of the Java programming language.
Just make the discountList field never null - ie initialized to an empty list - and iterate over it. Something like:
for (Discount discount : a.getCharges().getDiscounts().getDiscountList()) {
b.getList().get(0).setDiscountValue(discount.getValue());
b.getList().get(0).setDiscountName(discount.getName());
}
Your "senior" may need to do some research. The "performance impact" of doing this is a few bytes per object and a few microseconds per access. If he's really hung up about memory, initialise it with a LinkedList, which has almost no memory footprint.
In Java a variable V pointing to an object instance O is simply a numeric value pointing to a memory location where the object's data is stored.
When we assign Vto another variable V1 all that happens is that V1 now points to the same memory location where data for O is stored. This means that new memory is not allocated when you do simple assignment unlike C++ code where the = operator can be be overloaded to do a deep-copy in which case new memory is actually allocated. Illustrating with an example below
Consider a class like below
class Foo {
private List<String> barList = new ArrayList<>();
//class methods...
//getter for the list
List<String> getBarList() {
return this.barList;
}
}
public static void main(String[] args) {
Foo f = new Foo()
//the below lien will print 0 since there is no bar string added
System.out.println("Bar list size: " + f.getBarList().size());
// add a bar string. Observe here that I am simply getting the list
// and adding - similar to how your code is currently structured
f.getBarList().add("SomeString");
//now get a reference to the list and store it in a variable.
// Below anotherList only points to the same memory location
// where the original bar list is present. No new memory is allocated.
List<String> anotherList = f.getBarList();
//print the content of bar list and another list. Both will be same
for(String s : f.getBarList()) {
System.out.println(s);
}
for(String s: anotherList) {
System.out.println(s);
}
//add a new bar string using the reference variable
anotherList.add("Another string");
//print the content of bar list and another list. Both will be same. If anotherList had separate memory allocated to it then the new string added would be only seen when we print the content of anotherList and not when we print the content of f.getBarList(). This proves that references are only some numeric addresses that point to locations of the object on heap.
for(String s : f.getBarList()) {
System.out.println(s);
}
for(String s: anotherList) {
System.out.println(s);
}
}
Hope this helps.

ArrayList initialized to a size, but index is out of bounds and size is zero. Why?

So I am initializing an ArrayList of ArrayLists in order to have a set of resizable Arrays to hold the names of classes as strings for a Design Analyzer homework assignment. The ArrayLists are initialized to a size of 7 (For the test file that I am using), yet when I perform a get on element 1, I am getting an IndexOutOfBounds exception. Upon checking the size of the ArrayList causing the problem (providers), the size is zero. I am having a hard time understanding why the ArrayList is size zero, despite the fact that I have initialized it to be the size of my cls ArrayList (which is 7 in my test case). The exception is being thrown when I attempt the get(i) on providers in my if statement, but why? Any help would be appreciated.
public class DesignAnalyzer {
//private Hashtable classSet = new Hashtable();
//ArrayList<Integer> counters = new ArrayList<>();
private static ArrayList<ArrayList<String>> providers;
private static ArrayList<ArrayList<String>> clients;
//private static ArrayList<String>[]
public static void analyze(ArrayList<Class<?>> cls, String path){
Package homePkg = Package.getPackage(path.substring(path.lastIndexOf("\\")+1));
ArrayList<ArrayList<String>> providers = new ArrayList<ArrayList<String>>(cls.size());
ArrayList<ArrayList<String>> clients = new ArrayList<ArrayList<String>>(cls.size());
providers.ensureCapacity(cls.size());
clients.ensureCapacity(cls.size());
for(int i = 0; i < cls.size(); ++i){
providers.set(i, new ArrayList<String>());
clients.set(i, new ArrayList<String>());
}
getProviders(cls, homePkg);
getClients(cls);
//providers.clear();
}
private static void getProviders(ArrayList<Class<?>> cls, Package pkg){
for(int i = 0; i < cls.size(); ++i){
Class<?> spr = cls.get(i).getSuperclass();
int temp = providers.size(); //should be 7 in test case, but coming back as zero
if(spr != null && spr.getPackage().toString().equals(pkg.toString()) &&
!providers.get(i).contains(spr.toString())) // exception being thrown here at i = 1 b/c providers.size is zero...
providers.get(i).add(spr.toString());
The number that you pass to ArrayList's constructor is the initial capacity of the ArrayList, not the initial size. The initial size is 0, unless you are passing to the constructor (not the same constructor that takes the capacity parameter) another Collection used to populate your ArrayList.
You should never call providers.get(i) before checking that providers.size() > i.
P.S.
I see that you have code that initializes the providers ArrayList in your analyze method. However, you initialize a local variable and not the static class member of the same name. This means that getProviders should actually throw a NullPointerException and not IndexOutOfBoundsException (unless you initialize the providers static member in some code you didn't include).
Try to change your analyze method to :
public static void analyze(ArrayList<Class<?>> cls, String path){
Package homePkg = Package.getPackage(path.substring(path.lastIndexOf("\\")+1));
providers = new ArrayList<ArrayList<String>>(cls.size());
clients = new ArrayList<ArrayList<String>>(cls.size());
....
Accordingly to the documentation, such a constructor does what follows:
Constructs an empty list with the specified initial capacity.
So, it's perfectly reasonable that accessing it ends in an out of bound exception, for it's empty.
Something similar happens for ensureCapacity, that I see you are using in your code. It simply does what follows:
Increases the capacity of this ArrayList instance, if necessary, to ensure that it can hold at least the number of elements specified by the minimum capacity argument.
I guess you have misunderstood what capacity means for a container like ArrayList and what's actually the size. While the latter actually indicates how many items are there, the former is related to the internal representation of the container. As you know, such a container grows dynamically on demand, but you can slightly optimize it if you know which is the intended final size, as an example when used in algorithms bounded in terms of visited items.

Size or number of elements in an array of objects? in Java?

Ex.
Student[] storage = new Student[10];
After initialization, is there a method or anything i can do to return the # of objects created besides setting a counter?
If you use an array, the array size is fixed, so storage.length will always give you the array size. You will end up doing this to get number of instantiated objects:
for(Student s : storage){
if (s != null)
count ++;
}
1st Approach:
However, if you store the created objects within a list. You can simply get the number of objects by: list.size();
ArrayList<Student> list = new ArrayList<Student>();
list.add(new Student("Alice"));
list.add(new Student("Bob"));
2nd Approach:
You can also make a count in the class itself.
class Student{
private static int studCreated = 0;
public Student(){
studCreated ++; //Counts automatically
}
//Other constructors not shown here
public static int getStudCreated(){
return studCreated;
}
}
Everytime a new Student object gets instantiated, the Student constructor will be called, hence automatically update the number of objects created.
new Student("Alice");
new Student("Bob");
new Student("Carol");
System.out.println(Student.getStudCreated()); //Print num of Student obj instantiated.
3 will be printed, since constructor was called 3 times.

References and copying objects, unexpected behavior

I need to know why the following happens, in this code (the last two block) I expect the exact same output yet the local objects (who are mere references to the ones in the list, right?) are in their old state while the list is updated. I have a bug because of a similar copying procedure in my gamecode (tilebased, objects swap positions, so I thought why not just swap their references...)
Example:
package game;
import java.util.ArrayList;
public class Tester {
private String s;
private Foo foo;
public Tester(String s, String f) {
this.s = s;
this.foo = new Foo(f);
}
class Foo {
private String f;
public Foo(String f) {
this.f = f;
}
}
#Override
public String toString() {
return foo.f + ":" + s;
}
public void swap(Tester other) {
String tempS = this.s;
Foo tempFoo = this.foo;
this.s = other.s;
this.foo = other.foo;
other.s = tempS;
other.foo = tempFoo;
}
public static void main(String[] args) {
ArrayList<Tester> test = new ArrayList<Tester>();
test.add(new Tester("First", "1"));
test.add(new Tester("Second", "2"));
System.out.println("After initializing list");
for (Tester t : test) {
System.out.println(t);
}
Tester first = test.get(0);
Tester second = test.get(1);
Tester tmp = first;
first = second;
second = tmp;
System.out.println("\nAfter temps");
System.out.println(first);
System.out.println(second);
System.out.println("\nList changed after temps?");
for (Tester t : test) {
System.out.println(t);
}
System.out.println("\nAfter swap");
first.swap(second);
System.out.println(first);
System.out.println(second);
System.out.println("\nList after swap");
for (Tester t : test) {
System.out.println(t);
}
}
}
And the output:
After initializing list
1:First
2:Second
After temps
2:Second
1:First
List changed after temps?
1:First
2:Second
After swap
1:First
2:Second
List after swap
2:Second
1:First
I think I was a bit unclear, I always print out first then second (the objects) so "After swap" should look exactly like "List after swap", the list has changed after the swapping of the local objects, the local objects (again, mere references to the ones in the list?) have not.
To the comment in the answer: While my confusion is cleared and my problem solved I was asking whether it is possible to get the actual reference of the list to the object so that when I point it to something else the list will also automagically point to that something else. In the example below Foo a points first to object Foo with attribute A, but this reference it got from list.get(). Now if I point it to new Turtles() the list will still point to Foo with A.
I was hoping for a "hard" reference, so that when I point to turtles, the arraylist points to turtles.
This would make swapping easier but I am yet unsure of how to implement a list that can do this (if at all possible), this would suit the specific needs of my game very well.
What you need to bear in mind when working with objects is that the variable which holds the object doesn't actually represent the object. The value of the variable is a pointer in memory to the place where the object exists.
An ArrayList of a certain type of object, by extension, doesn't actually hold objects. It holds object references, or pointers to object locations in memory.
When you say:
Object a = new Object();
Object b = new Object();
a = b;
you're setting a to the value of the pointer to b; in other words, since both a and b point to the same object in memory, changing one changes the other.
Now to answer your question, with this in mind. If you pull two object references out of an ArrayList, and then swap them, you've swapped the references to the objects; however, the references haven't changed location in the ArrayList. This explains the first three outputs.
Once you do an internal swap, however, you've changed the values stored in each object. This means that, though the pointers to the first and second objects are still the same in memory, their internal information has been swapped.
This explains the last two outputs.
(Note, this is also why you have to use System.arraycopy instead of setting int[] a equal to int[] b; if you were to do the latter, then changing a would change b.)
Actually your swap method does not swap the objects themselves but only the values they are containing, the String s is swaped by value, the object foo is swaped by reference.
when you get an element from the list using get(index) you actually get a reference to that object in addition to that internal reference witch the list is holding, so you have there two references pointing to the same object.
to really swap element of a list you should be using the set method of the List with something like that:
Tester tmp = test.get(index);
test.set(index, test.get(index+1));
test.set(index+1, tmp);
this way the elements are swaped in the list so iterating over it will print the result you expect. the swap method you have will be obsolete.

error adding single element into structure array java

I am new to java and having an issue when trying to add a single element into a structure type array. I have my array setup as so: public apartment availableRoom[] = new apartment[1]; My main calls a method that initializes this as soon as the application launches:
availableRoom[0] = new apartment(150, 2, 200.00,null);
//this sets default values for room#, beds, price, and guest
My constructor takes the info like so
public apartment(int roomNum, int beds, double price, String guest )
{
this.roomNumber = roomNum;
this.roomBeds = beds;
this.nightlyFee = price;
this.roomGuest = guest;
}
Where I am having issues is when I am trying to assign a guest to the room. I am trying it with availableRoom[i].roomGuest = name Name is entered by the user and i is set to 0 (I checked). No errors but when I go to print the information for the room it returns every value as 0 and the guest to null. Can anyone see what I am doing wrong? (FYI Apartment is a separate class from main)
Main
public class apartmentMain {
static apartment action = new apartment();
public static void main(String[] args) {
action.createApt();
action.addGuest();
apartment.java
public void createApt()
{
availableRoom[0] = new apartment(150, 2, 200.00,null);
}
public void addGuest()
{
name = input.next();
availableRoom[i].roomGuest = name;
}
well, as you say
No errors but when I go to print the information for the room it returns every value as 0 and the guest to null.
I think , you are setting values in diffrent object and printing different one. If you just paste how you are printing its values it may help a lot.
Things to Consider
Since you are getting default values(that instance variables get if you don't assign any), that means an actual object is there in your array, that is instantiated but not initialized.
Take a close look which object you are printing and which one you are setting values in.
It is quite possible that at the first index, a newly instantiated object is inserted somehow that replaced the original one.
you are printing a different object than the original one ....a possibility.
You may want to get rid of the "no argument constructor" to better get actual seen of the problem. Try it..its worth.
Your program is not complete. I give a small example from which you can guess your error.
public class Demo
{
int x;
public static void main(String args[])
{
Demo d[] = new Demo[2];
d[0] = new Demo();
d[1] = new Demo();
d[0].x = 100;
d[1].x = 200;
System.out.println(d[0].x);
System.out.println(d[1].x);
}
}
Many people get wrong concept in the following code.
Demo d[] = new Demo[2];
You think a Demo array of 2 elements (with two Demo objects) with object d is created.
It is wrong. Infact, two reference variables of type Demo are created. The two
reference variables are to be converted int objects before they are used as follows.
d[0] = new Demo();
d[1] = new Demo();
With the above code, d[0] and d[1] becomes objects. Now check your code in these
lines.
You can find more details from Java Reference Variables – Objects – Anonymous objects

Categories