This program can count total number of objects but I am unable to count
the objects destroyed. How this can be done?
package displayobjno;
public class DisplayObjNo
{
public static void main(String[] args)
{
DisplayObject obj1 =new DisplayObject();
DisplayObject obj2 =new DisplayObject();
obj1=null; //How to count the objects being destroyed?
}
}
class DisplayObject
{
static int numOfObj;
DisplayObject()
{
numOfObj+=1;
}
}
You simply cannot do that in Java:
finalization is not guaranteed to run,
garbage collection is unpredictable and any assumption on GC is misleading
Both answers are naive and are not guaranteed to work.
Garbage collection is unpredictable and you should not base your program logic around it. This should be used only for debugging, educational purposes or, if absolutely necessary, optimizations.
You can store your DisplayObjects in a WeakHashMap.
An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use.
The number of elements in the map will be the number of reachable objects or those which have not been garbage collected yet.
Add this in class:
public void finalize() {
super.finalize();
numOfObj-=1;
}
However, this method will be called only when system is collecting garbage. I mean, there can be a situation which the usage of the object is end, but system do not collect them so the method will not be called.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have the below method.Suppose i call A.m1() 10,000 times from class B.
So all 10,000 MyObj objects will be garbage collected as their scope is only within the m1() method.
There is no memory leak?
class A {
String m1() {
MyObj obj = new Mybj();
}
}
And i call it below
class B {
void m2() {
String s = classAObj.m1();
}
}
The references created in the method are eventually garbage collected when they go out of scope. But it doesn't necessary happen immediately.
Here is a demo that shows that the references are collected. But first
some terms.
hard reference - A normal reference to an object that will be around until it is garbage collected. These are the typical instance values resulting from object creation.
weak references - references that point to the same object as a hard reference. When a hard reference is garbage collected, the associated weak references are also collected.
How this works.
The method m1 is called n times, each time creating a weak reference of an instance of A and returning it.
This is then added to a list.
Once the hard references are garbage collected, the weak references that refer to the same objects will also be collected
The weak reference will then return null when trying to retrieve its associated object.
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class GarbageCollection {
public static void main(String[] args) {
// get out of static context
new GarbageCollection().start();
}
public void start() {
int n = 10_000;
List<WeakReference<A>> weak = new ArrayList<>();
Create n weak references of A by calling m1 and returning the reference.
Then it add to the List.
for (int i = 0; i < n; i++) {
WeakReference<A> wk = m1();
weak.add(wk);
}
Now iterate thru the List of weak references to see how many are null.
Zero is expected since the garbage collector has not yet run. All of those A allocations created in m1 are still lurking around in the heap.
int count = 0;
for (WeakReference<A> wk : weak) {
if (wk.get() == null) {
count++;
}
}
System.out.println(count); // probably zero
Now repeat the same process but explicitly invoke the garbage collector.
count = 0;
System.gc();
for (WeakReference<A> wk : weak) {
if (wk.get() == null) {
count++;
}
}
At this point, count should be non-zero (or possibly n for small values of n) to show some or all of the objects have been collected.
System.out.println(count);
}
public WeakReference<A> m1() {
A a = new A();
return new WeakReference<>(a);
}
}
class A {
}
I think you have a C++ background. In Java, it's quite hard to get a memory leak because of its garbage collection system. Garbage collection can get complicated, but the basic idea is there is a program constantly running in the background looking in the heap for an unused object, and when it finds one, it deletes it. So when you exit the m1() method, there are no references to the new Mybj() object so the garbage collector deletes it.
Please consider the following bit of code :
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static List<String> arraylist=new ArrayList<String>();
//add hello n times to the list
public static void add_to_list(int n)
{
if(n==0)
{
return;
}
else
{
String b=new String("hello");
arraylist.add(b);
add_to_list(n-1);
}
}
public static void main(String args[]) throws IOException
{
add_to_list(5);
for(String s:arraylist)
{
System.out.println(s);
}
}
}
I have tried running this program multiple times and I get the same output as :
hello
hello
hello
hello
hello
My assumptions :
String b goes out of the scope once the method add_to_list is executed
I am referencing the arraylist reference indexes outside their scope
Arraylist contains the reference of the strings created in the method.
Hence my question is :
Is there a possibility that the references are cleaned up by the java collector before I print the value?
Did I just get lucky and the Java collector did not run before I read those values?
your variable arraylist is static, so doesn't go out of scope. It therefore maintains references to its element until the end of the program.
They can't be garbage collected, so you're not "just lucky".
When you create a String using new() operator, it always create a new object in heap memory. In your above code, every time add_to_list() is called it creates a new string object in heap memory and its reference is stored in local variable 'b' which resides in stack memory of add_to_list(). On every call to this method, fresh stack memory is allocated and upon finishing its execution for that particular call, its allocated stack memory is cleared.
But you also adding this string object reference i.e. 'b' to a static ArrayList. Static variables are stored as part of Class object associated with the class and resides in PermGen in Heap memory and will live as long as the class is in memory.
Garbage collection is always working to free memory by clearing any objects without any references. These are objects that are no longer being used. But in your above code all string references are stored in static list and thus they will be garbage collected only when class terminates.
I've read all the theory I can on how synchronised methods operate, but I need a practical example.
What is the positive and negative or using synchronised like this:
public class Test {
public static void main(String[] args){
boolean sync = Boolean.valueOf(args[0]);
Person person1 = person2 = new Person();
person1.write(sync, args[1]);
person1.read(sync);
person2.write(sync, args[1]);
person2.read(sync);
}
}
write is naming the project: (either synchronized or not)
public static String project_name = "";
and read is printing the current name for the person (either synchronized or not)
So what is the difference when write and read are regular methods versus synchronised methods?
What could go wrong if I use the regular method?
Quick answer:
A non-synchronous method being accessed by multiple sources will generally cause undefined behaviour, but a synchronised method will work every time.
Longer answer:
I don't think you fully understand what a synchronised method is, because your code does not demonstrate it at all.
If there really is a possibility of 100 people accessing the same method then you will have undefined behaviour when the same variable is being written to and read from.
However, if that method is accessed synchronously then each method call will be added to a queue and will happen in order.
For example:
100 different threads(People?) could call SynchronizedProjectName.renameProject("exampleName"); and/or SynchronizedProjectName.projectName(); on the code below, and no error would occur, and no read/write would happen at the same time.
public class SynchronizedProjectName {
private string project_name = "";
public synchronized void renameProject(String newProjectName) {
project_name = newProjectName;
}
public synchronized string projectName() {
return project_name;
}
}
You should always always use some sort of thread safe strategy when dealing with multiple threads/users, and if you don't, then you should expect your code to misbehave and probably crash.
See here for a little bit of extra info: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
I'm building a simple program to use in multi processes (Threads).
My question is more to understand - when I have to use a reserved word synchronized?
Do I need to use this word in any method that affects the bone variables?
I know I can put it on any method that is not static, but I want to understand more.
thank you!
here is the code:
public class Container {
// *** data members ***
public static final int INIT_SIZE=10; // the first (init) size of the set.
public static final int RESCALE=10; // the re-scale factor of this set.
private int _sp=0;
public Object[] _data;
/************ Constructors ************/
public Container(){
_sp=0;
_data = new Object[INIT_SIZE];
}
public Container(Container other) { // copy constructor
this();
for(int i=0;i<other.size();i++) this.add(other.at(i));
}
/** return true is this collection is empty, else return false. */
public synchronized boolean isEmpty() {return _sp==0;}
/** add an Object to this set */
public synchronized void add (Object p){
if (_sp==_data.length) rescale(RESCALE);
_data[_sp] = p; // shellow copy semantic.
_sp++;
}
/** returns the actual amount of Objects contained in this collection */
public synchronized int size() {return _sp;}
/** returns true if this container contains an element which is equals to ob */
public synchronized boolean isMember(Object ob) {
return get(ob)!=-1;
}
/** return the index of the first object which equals ob, if none returns -1 */
public synchronized int get(Object ob) {
int ans=-1;
for(int i=0;i<size();i=i+1)
if(at(i).equals(ob)) return i;
return ans;
}
/** returns the element located at the ind place in this container (null if out of range) */
public synchronized Object at(int p){
if (p>=0 && p<size()) return _data[p];
else return null;
}
Making a class safe for multi-threaded access is a complex subject. If you are not doing it in order to learn about threading, you should try to find a library that does it for you.
Having said that, a place to start is by imagining two separate threads executing a method line by line, in an alternating fashion, and see what would go wrong. For example, the add() method as written above is vulnerable to data destruction. Imagine thread1 and thread2 calling add() more or less at the same time. If thread1 runs line 2 and before it gets to line 3, thread2 runs line 2, then thread2 will overwrite thread1's value. Thus you need some way to prevent the threads from interleaving like that. On the other hand, the isEmpty() method does not need synchronization since there is just one instruction that compares a value to 0. Again, it is hard to get this stuff right.
You can check the following documentation about synchronized methods: http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
By adding the synchronized keyword two things are guaranteed to happen:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
So whenever you need to guarantee that only one thread accesses your variable at a time to read/write it to avoid consistency issues, one way is to make your method synchronized.
My advice to you is to first read Oracle's concurrency tutorial.
A few comments:
Having all your methods synchronized causes bottlenecks
Having _data variable public is a bad practice and will difficult concurrent programming.
It seems that you are reimplementing a collection, better use existing Java's concurrent collections.
Variable names would better not begin with _
Avoid adding comments to your code and try to have declarative method names.
+1 for everybody who said read a tutorial, but here's a summary anyway.
You need mutual exclusion (i.e., synchronized blocks) whenever it is possible for one thread to create a temporary situation that other threads must not be allowed to see. Suppose you have objects stored in a search tree. A method that adds a new object to the tree probably will have to reassign several object references, and until it finishes its work, the tree will be in an invalid state. If one thread is allowed to search the tree while another thread is in the add() method, then the search() function may return an incorrect result, or worse (maybe crash the program.)
One solution is to synchronize the add() method, and the search() method, and any other method that depends on the tree structure. All must be synchronized on the same object (the root node of the tree would be an obvious choice).
Java guarantees that no more than one thread can be synchronized on the same object at any given time. Therefore, no more than one thread will be able to see or change the internals of the tree at the same time, and the temporary invalid state created inside the add() method will be harmless.
My example above explains the principle of mutual exclusion, but it is a simplistic and inefficient solution to protecting a search tree. A more practical approach would use reader/writer locks, and synchronize only on interesting parts of the tree rather than on the whole thing. Practical synchronization of complex data structures is a hard problem, and whenever possible, you should let somebody else solve it for you. E.g., If you use the container classes in java.util.concurrent instead of creating your own data structures, you'll probably save yourself a lot of work (and maybe a whole lot of debugging).
You need to protect variables that form the object's state. If these variables are used in static method, you have to protect them as well. But, be careful, following example is wrong:
private static int stateVariable = 0;
//wrong!!!!
public static synchronized void increment() {
stateVariable++;
}
public synchronized int getValue() {
return stateVariable;
}
It seems that above is safe, but these methods operate on different locks. Above is more or less corresponds to following:
private static int stateVariable = 0;
//wrong!!!!
public static void increment() {
synchronized (YourClassName.class) {
stateVariable++;
}
}
public synchronized int getValue() {
synchronized (this) {
return stateVariable;
}
}
Notice that different locks are used when mixing static and object methods.
After reading the books, surfing the nets regarding the type of references in Java, I still have some doubts (or I may have interpreted the concept wrong).
It would be a great help for me if anyone clear my doubts.
Let me take an example of a class containing class variables, instance variables and local variables.
public class Test {
public static ArrayList<String> listCommon = new ArrayList<String>();
private HashMap<String, String> mapInstance;
public Test() {
mapInstance = new HashMap<String, String>();
}
public void doSomething(String key) {
ArrayList<String> local = new ArrayList<String>();
if(key != null){
local.add(mapInstance.get(key));
}
System.out.println("Value is added in instance Map: ", mapInstance.get(key));
}
}
My Question are;
1. are listCommon (static variable) and mapInstance (instance variable) Strong reference towards Garbage Collector?
2. Is variable local (defined and used in method) a Weak reference?
3. How the Phantom reference and Soft reference came in picture?
4. OR above 3 concepts are invalid; means that Java defines the references only if you explicitly used the type defined in java.lang.ref package?
Any help would be great for me.
are listCommon (static variable) and mapInstance (instance variable) Strong reference towards Garbage Collector?
They are strong references, yes.
Is variable local (defined and used in method) a Weak reference?
No, it is a local variable, so it is a variable, so it is still a strong reference.
How the Phantom reference and Soft reference came in picture?
If you use them. If you don't use them you don't need to worry about them. They are for writing various kinds of caches really.
OR above 3 concepts are invalid; means that Java defines the references only if you explicitly used the type defined in
java.lang.ref package?
Reference variables are always strong. The other kinds only arise when you use them explicitly.
Answer to questions:
Yes, they are strong reference. Weak Reference are defined using Weak reference Object.
No, reason as 1).
Phantom Reference doesn't apply in your example. By default, all instances are strong reference.
Yes, you specify weak/phantom reference using the java.lang.ref package. By default, strong reference is used.
Note: A wikipedia explaination of Weak Reference might be useful.
Read this blog post about variable references.
** Update **
An atomic reference is an object referenced in such a way that it is accessed atomically; meaning that there are no race condition accessing it. For example:
class RaceTest {
static private int count = 0;
static public void main(String...args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i=0; i<1000000; i++) {
count++;
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
for (int i=0; i<1000000; i++) {
count--;
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Final count (should be 0) = " + count);
}
}
Will spawn two threads that 1) will increment count and 2) will decrement it. Now, both threads will run in parallel and the program will wait until both terminate (at the join point). A common idea would be that since both threads have the same loop (will loop the same amount of time), each will "cancel" each other's operation and thus count should be 0, but this is not the case. Why? Because while, for example, t1 may want to increase the variable, such operation is not atomic, but is more in the order of : get, inc, set. So there may be cases that, even before the second operation inc is made, t2 would have accessed the variable and dec the variable, thus t1 would have had actually +2 the variable. And vice versa in an indefinite manner. (Each run of the code would produce a different value.)
Now, replacing int by AtomicInteger and using incrementAndGet() or decrementAndGet() will solve the issue by rendering the get, inc, set into a single operation, and eliminating the race condition in the code.