Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 
Search the JavaFAQ.nu
1000 Java Tips ebook

1000 Java Tips - Click here for the high resolution copy!1000 Java Tips - Click here for the high resolution copy!

Java Screensaver, take it here

Free "1000 Java Tips" eBook is here! It is huge collection of big and small Java programming articles and tips. Please take your copy here.

Take your copy of free "Java Technology Screensaver"!.

Easy Learn Java: Programming Articles, Examples and Tips - Page 395


Previous 1060 Stories (530 Pages, 2 Per Page) Next

Counting Objects Clandestinely

Go to all tips in Story by Dr. Kabutz

The Java Specialists' Newsletter [Issue 038a] - Counting Objects Clandestinely

Author: Dr. Heinz M. Kabutz

JDK version:

Category: Performance

You can subscribe from our home page: http://www.javaspecialists.co.za (which also hosts all previous issues, available free of charge Smile

Welcome to the 38th edition of "The Java(tm) Specialists' Newsletter", sent to 2226 Java experts in 70 countries, with Egypt as latest addition. I'm missing a few African countries, ok, it's worse than missing, I only have South Africa, Ghana, Nigeria, Zimbabwe and Egypt, so if you are from another African country, please send me an email.

Talking about Africa, I didn't include Mauritius in my list of African countries, although politically I probably should have. If you don't know what Mauritius is, it is a small island in the Indian Ocean inbetween South Africa and India. Mauritius was colonised by the French (who only drank and fought and never did much for the country except introduce bureaucracy Wink and later properly colonised by the British. The result is that English is the official language, whereas French (and derivatives thereof) is the spoken language.

The people in Mauritius are amazing. Extremely friendly, and not only to sell you things. The beaches are fantastic, the water warm, lots of things to see and do, such as waterskiing, etc. Oh, and the hotels! Such service you've never seen anywhere. So, surprise, surprise, I am running my course "Design Patterns - The Timeless Way of Coding" on that beautiful island in February through a Mauritian company (yes, life is tough for us Java programmers Wink.

Counting Objects Clandestinely

A few months ago I received a frantic phone call from a friend who had gotten himself seriously stuck. His program was running out of memory and he didn't know where the objects were being created. He ran his program in a commercial memory analyser, which only had the effect that the memory analyser crashed. (If you want to have a laugh, try running any big Java application (e.g. Together/J or JBuilder 4) in a memory analyser). If it runs, you'll see that the success of your product does not depend on good programming but on good marketing.

The trick I'm going to show you in this newsletter essentially saved my friend's project, and it is sooo easy and cheap, you won't believe it. Please note however, that this is only an initial implementation and that you should extend the functionality if you want to use it a lot. I have myself used this idea to effectively find memory problems in my own applications.

Imagine for a second that there was some way of knowing when an Object was created. Well, if you really want that functionality, why don't you add it? Yes, why don't you change java/lang/Object? Sure, it's intrusive, but very effective. The test code that you add to your code to find the memory leaks would be removed anyway (or commented out?) before the final build, so why not? It took me a while to get all this right, which is why you didn't see a newsletter for a while, but here is the code, which I tried on Windows JDK 1.3.1. On other VMs it might reformat your harddrive, sell your credit card details or promote you to sales manager.

package java.lang;
import java.util.*;
public class Object {
  // ... stick this at the bottom of Object.java:
  private static HashMap countMap = new HashMap();
  private static boolean counting = true;
  private static int totalObjects = 0;

  private class Counter {
    int value = 1;
  }

  public Object() {
    synchronized(Object.class) {
      if (counting) {
        counting = false;
        totalObjects++;
        Counter c = (Counter)countMap.get(getClass());
        if (c == null) {
          countMap.put(getClass(), new Counter());
        } else {
          c.value++;
        }
        counting = true;
      }
    }
  }
  public synchronized static void ___resetObjectCreationStats() {
    counting = false;
    totalObjects = 0;
    countMap.clear();
    counting = true;
  }
  public static void ___printObjectCreationStats() {
    ___printObjectCreationStats(System.out);
  }
  public synchronized static void ___printObjectCreationStats(java.io.PrintStream out) {
    counting = false;
    out.println("Total number of objects: " + totalObjects);
    TreeSet sorted = new TreeSet(new Comparator() {
      public int compare(Object o1, Object o2) {
        int value1 = ((Counter)((Map.Entry)o1).getValue()).value;
        int value2 = ((Counter)((Map.Entry)o2).getValue()).value;
        int result = value2 - value1;
        if (result == 0) {
          String classname1 = ((Class)((Map.Entry)o1).getKey()).getName();
          String classname2 = ((Class)((Map.Entry)o2).getKey()).getName();
          return classname1.compareTo(classname2);
        }
        return result;
      }
    });
    sorted.addAll(countMap.entrySet());
    Iterator it = sorted.iterator();
    while(it.hasNext()) {
      Map.Entry entry = (Map.Entry)it.next();
      out.println("	" + ((Counter)entry.getValue()).value
        + "	" + ((Class)entry.getKey()).getName());
    }
    out.println();
    counting = true;
  }
}

You can now know exactly how many objects were created since you last reset the counters. [Actually, not really exactly. This approach will not tell you when arrays are created, but you will find out about any non-array objects that were made.] The way you would use this in your code is as follows:


import java.util.*;
public class Test {
  public static void testStringConcatenation() {
    ___resetObjectCreationStats();
    int localHost = 0x7F000001;
    String s =
      ((localHost>>24)&0xff) + "."
      + ((localHost>>16)&0xff) + "."
      + ((localHost>>8)&0xff) + "."
      + (localHost&0xff);
    System.out.println("Objects created to make an IP address String");
    System.out.println("--------------------------------------------");
    ___printObjectCreationStats();
  }
  public static void testLinkedListCreation() {
    ___resetObjectCreationStats();
    LinkedList daysOfWeek = new LinkedList();
    System.out.println("Objects created to make a LinkedList");
    System.out.println("------------------------------------");
    ___printObjectCreationStats();
    daysOfWeek.add("Sunday");
    daysOfWeek.add("Monday");
    daysOfWeek.add("Tuesday");
    daysOfWeek.add("Wednesday");
    daysOfWeek.add("Thursday");
    daysOfWeek.add("Friday");
    daysOfWeek.add("Saturday");
    System.out.println("and after adding 7 elements to the LinkedList");
    System.out.println("---------------------------------------------");
    ___printObjectCreationStats();
  }
  public static void testHashMapCreation() {
    ___resetObjectCreationStats();
    HashMap monthsVsLength = new HashMap();
    System.out.println("Objects created to make a HashMap");
    System.out.println("---------------------------------");
    ___printObjectCreationStats();
    monthsVsLength.put("January", new Integer(31));
    monthsVsLength.put("February", new Integer(28));
    monthsVsLength.put("March", new Integer(31));
    monthsVsLength.put("April", new Integer(30));
    monthsVsLength.put("May", new Integer(31));
    monthsVsLength.put("June", new Integer(30));
    monthsVsLength.put("July", new Integer(31));
    monthsVsLength.put("August", new Integer(31));
    monthsVsLength.put("September", new Integer(30));
    monthsVsLength.put("October", new Integer(31));
    monthsVsLength.put("November", new Integer(30));
    monthsVsLength.put("December", new Integer(31));
    System.out.println("and after adding 12 elements to the HashMap");
    System.out.println("-------------------------------------------");
    ___printObjectCreationStats();
  }
  public static void main(String args[]) {
    System.out.println("Objects created to get the VM started");
    System.out.println("-------------------------------------");
    ___printObjectCreationStats();
    testStringConcatenation();
    testLinkedListCreation();
    testHashMapCreation();
  }
}

When you compile the test class you should also at the same time point it to your Object.class otherwise you'll get a compiler moan. You have to run Test by including the new Object.class file in your bootclasspath, for example java -Xbootclasspath/p:. Test, which will prepend the current directory to the boot classpath. The output is rather long and would be different for each VM version.

Objects created to get the VM started
-------------------------------------
Total number of objects: 784
        514     java.util.Hashtable$Entry
        104     java.lang.String
        25      java.lang.StringBuffer
        22      java.util.Locale
        13      java.io.File
        11      sun.security.action.GetPropertyAction
*snip - run it yourself to see the rest*

Objects created to make an IP address String
--------------------------------------------
Total number of objects: 6
        5       java.lang.String
        1       java.lang.StringBuffer

Objects created to make a LinkedList
------------------------------------
Total number of objects: 2
        1       java.util.LinkedList
        1       java.util.LinkedList$Entry

and after adding 7 elements to the LinkedList
---------------------------------------------
Total number of objects: 9
        8       java.util.LinkedList$Entry
        1       java.util.LinkedList

Objects created to make a HashMap
---------------------------------
Total number of objects: 1
        1       java.util.HashMap

and after adding 12 elements to the HashMap
-------------------------------------------
Total number of objects: 25
        12      java.lang.Integer
        12      java.util.HashMap$Entry
        1       java.util.HashMap

What are the disadvantages of this approach, and what are the alternatives? The disadvantages that I can think of immediately are that you don't see the arrays like this and that you cannot see where objects were created from. I don't know how to solve the problems with the arrays, but you could easily change the code to also remember the stack trace of each object that gets constructed. You could then analyse the stack traces and find out exactly where the objects are constructed from. The alternatives I can think of is to use java -Xrunhprof (to perform JVMPI heap, cpu, or monitor profiling) or to use an expensive commercial tool. The disadvantage of some of the commercial tools is that if your program quickly eats memory the memory tools tend to fall on their back and play dead.

Have you ever wondered why Swing is so slow? Have a look at this test code:

import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.event.*;

public class TestGUI extends JFrame {
  public TestGUI() {
    super("TestGUI");
    getContentPane().add(new JTextArea(), BorderLayout.CENTER);
    JButton press = new JButton("Press Me!");
    press.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        ___printObjectCreationStats();
        ___resetObjectCreationStats();
      }
    });
    getContentPane().add(press, BorderLayout.SOUTH);
    setSize(500, 600);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    show();
  }
  public static void main(String[] args) {
    new TestGUI();
  }
}

I ran this code and moved my mouse in circles for 10 seconds in the JTextArea. Here are the first couple of entries that were shown when I pressed the "Press Me!" button:

     Total number of objects: 15622
        2867    java.lang.String
        1545    java.lang.ref.Finalizer
        1384    java.awt.event.MouseEvent
        1326    java.awt.Point
        1200    java.lang.StringBuffer
        1047    java.util.Hashtable$Entry
        769     java.util.WeakHashMap$WeakKey
        750     java.awt.EventQueueItem
        706     sun.awt.EventQueueItem
        648     java.awt.Rectangle
        316     sun.java2d.loops.GraphicsPrimitiveProxy
        266     sun.awt.MostRecentKeyValue
        253     java.awt.geom.AffineTransform
        134     java.util.HashMap$Entry

Why so many Strings? I can only assume that that has to do with the pluggable look & feel. The reason I say that is because if I press the button again (after moving the mouse in circles a few times), I get the following output:

Total number of objects: 5257
        891     java.lang.ref.Finalizer
        831     java.awt.event.MouseEvent
        796     java.awt.Point
        456     java.util.WeakHashMap$WeakKey
        436     java.awt.EventQueueItem

It gets quite interesting when we look at different VMs, just remember the warning at the beginning of this newsletter Wink

That's all for this week and this year. I wish you all the best for 2002, may you find much opportunity to tell others about this newsletter Wink [and make me prosper in the process ;]

Kind regards, and now I must get back to spending a few sunny days with my wife & two kiddies.

Heinz


Copyright 2000-2004 Maximum Solutions, South Africa

Reprint Rights. Copyright subsists in all the material included in this email, but you may freely share the entire email with anyone you feel may be interested, and you may reprint excerpts both online and offline provided that you acknowledge the source as follows: This material from The Java(tm) Specialists' Newsletter by Maximum Solutions (South Africa). Please contact Maximum Solutions for more information.

Java and Sun are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Maximum Solutions is independent of Sun Microsystems, Inc.

11919 bytes more | comments? | Printer Friendly Page  Send to a Friend | Score: 4
Posted by jalex on Saturday, August 20, 2005 (00:00:00) (2370 reads)

What is Java Isolates and why do we need it?

Go to all tips in Good To Know

There is a strong desire for multitasking to get more work out of the Java
virtual machine. The negative effects of large initial footprint, large
increments of memory required by additional applications, and long startup
latencies, all hurt Java's ability to compete with more nimble and efficient
language systems and bring into doubt the prospects for scalability.



The need for freedom from inter application interference remains high as users
of Java mix ever more varied applications in their cell phones, on their
desktops and within their servers.



Ad hoc script and native code mechanisms for controlling and load balancing
multiple Java virtual machines in server settings hurt portability,
maintainability and robustness. There is a need for simple yet effective control
mechanisms that are tightly focused on Java applications instead of their
implementation artifacts.


Java Isolates in an API. This API provides a uniform mechanism for
managing Java application life cycles that are isolated from each other, at
least with respect to object reachability, but that can potentially share
underlying implementation resources. It provides a means of deploying new Java
implementation features that enable and enhance scalability while providing an
alternative to ad hoc control schemes.

The API is intended to dictate implementation as little as possible. Different
implementations may provide different levels of isolation. All conformant
implementations must guarantee at least isolation of Java state (i.e. logically
disjoint heap spaces, per application mutable static fields, etc). Additional
forms of isolation possible include separation of JNI state and separation of
process state. Current Java implementations that provide execution of
applications in separate virtual machine instances can be wrapped with the
Isolation API by adding only a few mechanisms for control. Other implementations
might arrange for Java isolation in combination with high degrees of class,
bytecode, and native code sharing within the same VM or between multiple VMs.
Research by Sun and IBM has demonstrated these additional forms of isolation and
sharing.



Selection of implementation specific features within the context of this API
will be via a combination of vendor specific and standard command line arguments
and properties. There will be a way to detect and select specific features so
API users know what they're getting. Additional interfaces may be required to
control implementation features related to isolation and sharing, but these are
outside the scope of this API.



The API consists of the Isolate class, which can be thought of as a handle to an
isolated computation, and a few new exception classes. Isolate object
instantiation corresponds to preparation of an isolated computation (an
application). Methods for starting, suspending, resuming, and terminating the
isolated computation are present, as well as methods for determining state,
waiting for termination, and determining familial relationships of computations.



Isolate operations that alter state make security checks that can throw security
exceptions. Isolate objects for access to existing computations can be obtained
through a static lookup method using identifiers that are unique within the
platform's domain (e.g. a computer, a cluster, etc).



Because computations managed by the API are isolated and, therefore, cannot be
expected to be able to detect the presence of each other except through use of
the Isolation API, we expect there to be a need for inter application
communication. No new communication mechanism is included with this API, and the
API does nothing to inhibit use of standard Java mechanisms like RMI. In
particular, the only dictated distinction between parent and child isolated
computations is the unique identifier of each: no object sharing between family
members is implied or provided by the API.



Resource control of isolated computations is outside the scope of this API. We
recognize that future efforts to add resource control APIs to the Java platform
will have to take this API into account.


A short description of the underlying technology.


The technology used to implement this API will vary widely depending on the
qualities of isolation (and sharing) SDK implementers are able to deliver with
it. A minimal conformant implementation delivering no additional qualities will
define the API's constructors or factory methods and regular methods but in most
cases may respond with an exception to signal the lack of new capabilities. A
key point here is that this API is not intended to put any onerous burdens on
SDK implementers.



A more effective implementation will extend the current process creation,
monitoring and control mechanisms available to many VMs. Means of starting,
suspending, resuming and terminating applications in other VM processes will be
implemented with IPC mechanisms such as signals and/or RPC. A key aspect of this
simple implementation is the capability of the Java VM to pause execution of the
Java application. This capability is already present in most VMs for properly
handling garbage collection.



Other implementations will add the ability of the API to create and manage
applications sharing a VM but isolated from each other at least at the Java
state level by arranging for separate logical or physical heaps, automatic
replication of mutable static class information and static system resources, and
handling of execution control with the proper granularity. Proper control of
native code generation and sharing by in-runtime compilers would complete the
collection of single-VM implementation features.



Other implementations of the API will add selectable features for explicit or
transparent resource sharing of immutable class data, byte codes and native
(compiled) code between VM processes.


Very good artincle on "Java Isolates" (By: Murali Kaundinya) can be
found here.

Look at this short excerpt:


"What Is Wrong with Classloaders?

Classloaders make it possible to load multiple instances of the same class. It's
possible to modify the search mechanism for class files within the JVM.
Classloaders act like a namespace whereby the classes loaded by a particular
classloader are tagged to provide a unique identity. With classloaders, it's
also possible to dynamically modify the bytecodes just prior to their loading by
performing certain transformations. An application can be unloaded by discarding
its classloader. However, a classloader can only be discarded if the reference
count for all the classes loaded by this classloader becomes zero and the
garbage collector deems them as unreachable. Classloader share basic classes;
this can be exploited to change the shared data, thus making the other
classloader and its applications vulnerable. The security model is debatable at
best. Here's an example: if there exists a utility class that's used by an
application and that application is distributed across two separate
classloaders, replicating the utility class in both of these classloaders is
obviously expensive. It's certainly possible to create a hierarchy of
classloaders and having the parent classloader load the utility class, thus
allowing the two classloaders to share code. Isolation provided by classloaders
is weak because objects can leak and be captured. This approach therefore is
incomplete and error-prone."



This article is based on JSR 121: Application Isolation API Specification, http://www.jcp.org/en/jsr/detail?id=121
and

"Java preps dive into real-time role" article at http://symbian.sys-con.com/read/99716.htm



7318 bytes more | comments? | Printer Friendly Page  Send to a Friend | Score: 4
Posted by Anonymous on Wednesday, August 17, 2005 (00:00:00) (5186 reads)

Previous 1060 Stories (530 Pages, 2 Per Page) Next

530| 529| 528| 527| 526| 525| 524| 523| 522| 521| 520| 519| 518| 517| 516| 515| 514| 513| 512| 511| 510| 509| 508| 507| 506| 505| 504| 503| 502| 501| 500| 499| 498| 497| 496| 495| 494| 493| 492| 491| 490| 489| 488| 487| 486| 485| 484| 483| 482| 481| 480| 479| 478| 477| 476| 475| 474| 473| 472| 471| 470| 469| 468| 467| 466| 465| 464| 463| 462| 461| 460| 459| 458| 457| 456| 455| 454| 453| 452| 451| 450| 449| 448| 447| 446| 445| 444| 443| 442| 441| 440| 439| 438| 437| 436| 435| 434| 433| 432| 431| 430| 429| 428| 427| 426| 425| 424| 423| 422| 421| 420| 419| 418| 417| 416| 415| 414| 413| 412| 411| 410| 409| 408| 407| 406| 405| 404| 403| 402| 401| 400| 399| 398| 397| 396|
395
| 394| 393| 392| 391| 390| 389| 388| 387| 386| 385| 384| 383| 382| 381| 380| 379| 378| 377| 376| 375| 374| 373| 372| 371| 370| 369| 368| 367| 366| 365| 364| 363| 362| 361| 360| 359| 358| 357| 356| 355| 354| 353| 352| 351| 350| 349| 348| 347| 346| 345| 344| 343| 342| 341| 340| 339| 338| 337| 336| 335| 334| 333| 332| 331| 330| 329| 328| 327| 326| 325| 324| 323| 322| 321| 320| 319| 318| 317| 316| 315| 314| 313| 312| 311| 310| 309| 308| 307| 306| 305| 304| 303| 302| 301| 300| 299| 298| 297| 296| 295| 294| 293| 292| 291| 290| 289| 288| 287| 286| 285| 284| 283| 282| 281| 280| 279| 278| 277| 276| 275| 274| 273| 272| 271| 270| 269| 268| 267| 266| 265| 264| 263| 262| 261| 260| 259| 258| 257| 256| 255| 254| 253| 252| 251| 250| 249| 248| 247| 246| 245| 244| 243| 242| 241| 240| 239| 238| 237| 236| 235| 234| 233| 232| 231| 230| 229| 228| 227| 226| 225| 224| 223| 222| 221| 220| 219| 218| 217| 216| 215| 214| 213| 212| 211| 210| 209| 208| 207| 206| 205| 204| 203| 202| 201| 200| 199| 198| 197| 196| 195| 194| 193| 192| 191| 190| 189| 188| 187| 186| 185| 184| 183| 182| 181| 180| 179| 178| 177| 176| 175| 174| 173| 172| 171| 170| 169| 168| 167| 166| 165| 164| 163| 162| 161| 160| 159| 158| 157| 156| 155| 154| 153| 152| 151| 150| 149| 148| 147| 146| 145| 144| 143| 142| 141| 140| 139| 138| 137| 136| 135| 134| 133| 132| 131| 130| 129| 128| 127| 126| 125| 124| 123| 122| 121| 120| 119| 118| 117| 116| 115| 114| 113| 112| 111| 110| 109| 108| 107| 106| 105| 104| 103| 102| 101| 100| 99| 98| 97| 96| 95| 94| 93| 92| 91| 90| 89| 88| 87| 86| 85| 84| 83| 82| 81| 80| 79| 78| 77| 76| 75| 74| 73| 72| 71| 70| 69| 68| 67| 66| 65| 64| 63| 62| 61| 60| 59| 58| 57| 56| 55| 54| 53| 52| 51| 50| 49| 48| 47| 46| 45| 44| 43| 42| 41| 40| 39| 38| 37| 36| 35| 34| 33| 32| 31| 30| 29| 28| 27| 26| 25| 24| 23| 22| 21| 20| 19| 18| 17| 16| 15| 14| 13| 12| 11| 10| 9| 8| 7| 6| 5| 4| 3| 2| 1|


Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy