Home > Archive > Java Help > February 2006 > Why is it so big?!
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Why is it so big?!
|
|
| odwrotnie 2006-02-18, 6:58 pm |
| I hava a class with little amount of plenty of functions. Its object has
6816 bytes.
I was cuorious why is it SO BIG!!! I have found that an object of the same
class with "public int a() {return a;}" method has 72 more bytes!
Isn't it strange?! I thought that objects doesn't carry its methods, that
they only have...
Can anybody tell my why is it so?
--
Best regards,
Odwrotnie.
| |
| Roedy Green 2006-02-18, 9:57 pm |
| On Sun, 19 Feb 2006 00:21:48 +0100, odwrotnie <kruskal@gazeta.pl>
wrote, quoted or indirectly quoted someone who said :
>I hava a class with little amount of plenty of functions. Its object has
>6816 bytes.
>I was cuorious why is it SO BIG!!! I have found that an object of the same
>class with "public int a() {return a;}" method has 72 more bytes!
>
>Isn't it strange?! I thought that objects doesn't carry its methods, that
>they only have...
There are sever thing that bloat class files:
1. names. Unlike other languages the names of all the fields and
methods are in the class file, with whacking great package names.
2. initialisation. I've heard it has been improved in 1.5 or 1.6, but
he way it used to work it generated code roughly like this to handle
array initialisation
a[0] = new Integer( 2 );
a[1] = " abcd";
a[2] = ....
rather than converting the net effect into a great string of bytes to
be blasted into place in some sort of bulk process.
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
| |
| Roedy Green 2006-02-18, 9:57 pm |
| On Sun, 19 Feb 2006 00:21:48 +0100, odwrotnie <kruskal@gazeta.pl>
wrote, quoted or indirectly quoted someone who said :
>I hava a class with little amount of plenty of functions. Its object has
>6816 bytes.
look at it with a hex editor. look at it with a tool that understand
the format. see http://mindprod.com/jgloss/jasm.html
Disassemble it.
See http://mindprod.com/jgloss/disassemble.html
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
| |
| odwrotnie 2006-02-18, 9:57 pm |
| On Sun, 19 Feb 2006 00:21:48 +0100, odwrotnie <kruskal@gazeta.pl> wrote:
> I hava a class with little amount of plenty of functions. Its object has
> 6816 bytes.
> I was cuorious why is it SO BIG!!! I have found that an object of the
> same class with "public int a() {return a;}" method has 72 more bytes!
>
> Isn't it strange?! I thought that objects doesn't carry its methods,
> that they only have...
>
> Can anybody tell my why is it so?
>
Is there any possibility to make it work like in C++? So the size of an
object will depend only on fields, without methods?
I think that this is without sense!!!
--
Best regards,
Odwrotnie.
| |
| Roedy Green 2006-02-19, 7:56 am |
| On Sun, 19 Feb 2006 04:16:30 +0100, odwrotnie <kruskal@gazeta.pl>
wrote, quoted or indirectly quoted someone who said :
>
>Is there any possibility to make it work like in C++? So the size of an
>object will depend only on fields, without methods?
it does. There are two quite different things:
1. the class file which contains only methods and field descriptors.
2. the instantiated objects which contain only fields without any
methods, just a pointer to the vtables that points to the a single
common copy of the methods.
there is no size of operator in Java so you really don't know how big
objects in RAM are unless you start p ing under the hood.
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
| |
| Thomas Hawtin 2006-02-19, 7:56 am |
| Roedy Green wrote:
>
> 1. names. Unlike other languages the names of all the fields and
> methods are in the class file, with whacking great package names.
Names seem to take up most of the room. If you have it available on your
machine, running strings over class files will produce a surprising
amount. To see more details of what's in class files, use javap -c.
Class files are usually individually compressed in a zip (jar), so don't
take up so much space on disk or when downloading. The pack200 format,
takes a collections of class files and removes redundancy to produce a
more compressed image for downloading. Something similar is done for JRE
installation. JREs aren't *that* enormous to download, but I have an
(uncompressed) rt.jar file here of 47421098 bytes (45 MB).
> 2. initialisation. I've heard it has been improved in 1.5 or 1.6, but
> he way it used to work it generated code roughly like this to handle
> array initialisation
>
> a[0] = new Integer( 2 );
> a[1] = " abcd";
> a[2] = ....
I don't think 1.5 or 1.6 changes any of this, AFAIK. 1.5 does allow
..class constants to be loaded in a single load constant instruction,
rather than going through Class.forName and saving the result.
> rather than converting the net effect into a great string of bytes to
> be blasted into place in some sort of bulk process.
You can, of course, compact arrays into strings if you wish.
Tom Hawtin
--
Unemployed English Java programmer
http://jroller.com/page/tackline/
| |
| odwrotnie 2006-02-19, 7:00 pm |
| On Sun, 19 Feb 2006 12:17:56 +0100, Roedy Green
<my_email_is_posted_on_my_website@munged.invalid> wrote:
> there is no size of operator in Java so you really don't know how big
> objects in RAM are unless you start p ing under the hood.
I did check it in this way:
Runtime.getRuntime().freeMemory();
create onject;
Runtime.getRuntime().freeMemory();
The difference between this two values gave me the answer...
Is it wrong doing?
--
Best regards,
Odwrotnie.
| |
| Alan Krueger 2006-02-19, 7:00 pm |
| odwrotnie wrote:
> On Sun, 19 Feb 2006 12:17:56 +0100, Roedy Green
> <my_email_is_posted_on_my_website@munged.invalid> wrote:
>
>
> I did check it in this way:
> Runtime.getRuntime().freeMemory();
> create onject;
> Runtime.getRuntime().freeMemory();
>
> The difference between this two values gave me the answer...
>
> Is it wrong doing?
If your creation code causes a class to be loaded, the difference will
include all the information for that class and any dependent classes
that also needed to be loaded.
| |
| Roedy Green 2006-02-19, 7:00 pm |
| On Sun, 19 Feb 2006 18:13:32 +0100, odwrotnie <kruskal@gazeta.pl>
wrote, quoted or indirectly quoted someone who said :
>I did check it in this way:
>Runtime.getRuntime().freeMemory();
>create onject;
>Runtime.getRuntime().freeMemory();
Do it many times, and see what happens. The smallest increment is the
actual size of your object.
Also read up on exactly that freeMemory means. I don't know off hand,
but it might not be all that straightforward.
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
| |
| odwrotnie 2006-02-19, 7:00 pm |
| OK...
So Java objects has or has not to carry methods information?
Why an object which has only 2D array made of 36 int's is taking space of
6KB?!
--
Best regards,
Odwrotnie.
| |
| Thomas Hawtin 2006-02-20, 7:57 am |
| odwrotnie wrote:
>
> So Java objects has or has not to carry methods information?
Typically a Java object will keep a single hidden reference to
information about its class (some JVMs may optimise this away in certain
situations). This is much the same as a C++ object for a class with at
least one virtual method.
> Why an object which has only 2D array made of 36 int's is taking space
> of 6KB?!
Be very careful as to what you are measuring. First time you run your
code you will be loading it. That will take some memory. Also there are
issues with garbage collection. For instance typically each thread (or
possibly hardware thread) will have its own allocation buffer. Using
System.gc() may help hide some of the effects.
A simple test case:
class AnObject {
int[][] data = new int[6][6];
}
class MakeObject {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.gc();
long start = runtime.freeMemory();
AnObject a = new AnObject();
System.gc();
System.err.println(start - runtime.freeMemory());
AnObject b = new AnObject();
System.gc();
System.err.println(start - runtime.freeMemory());
}
}
Gives me:
360
656
So about 296 bytes for your allocation. We have allocated one object
(AnObject) with one reference, one array of six references and six
arrays of six integers. Assuming an object overhead of 12 bytes, four
byte for array length, four byte references and rounding up to multiples
of eight bytes gives: 16 + 40 + 6*40 = 296 bytes. Spot on.
Tom Hawtin
--
Unemployed English Java programmer
http://jroller.com/page/tackline/
| |
| Boris Gorjan 2006-02-20, 7:57 am |
| Roedy Green wrote:
> On Sun, 19 Feb 2006 00:21:48 +0100, odwrotnie <kruskal@gazeta.pl>
> wrote, quoted or indirectly quoted someone who said :
>
>
>
>
> There are sever thing that bloat class files:
>
> 1. names. Unlike other languages the names of all the fields and
> methods are in the class file, with whacking great package names.
>
> 2. initialisation. I've heard it has been improved in 1.5 or 1.6, but
> he way it used to work it generated code roughly like this to handle
> array initialisation
>
> a[0] = new Integer( 2 );
> a[1] = " abcd";
> a[2] = ....
>
> rather than converting the net effect into a great string of bytes to
> be blasted into place in some sort of bulk process.
>
>
3. Every java class extends at least java.lang.Object. Meaning: it's not "empty"
by default.
4. All the methods in Java are virtual. Meaning: even if they're not meant to be
used that way, there's some overhead.
5. ?
Which JVM and OS are you using?
BTW: what does "little amount of plenty of functions" mean?
| |
| Roedy Green 2006-02-21, 7:03 pm |
| On Mon, 20 Feb 2006 12:45:02 +0100, Boris Gorjan <borigor@hotmail.com>
wrote, quoted or indirectly quoted someone who said :
>4. All the methods in Java are virtual. Meaning: even if they're not meant to be
>used that way, there's some overhead.
Does virtuality fluff up the class file? Does each method explicitly
name its super-method? I don't think there would be any need to.
The loader can sort all that out from the attributes of the methods.
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
| |
| Roedy Green 2006-02-21, 7:03 pm |
| On Mon, 20 Feb 2006 11:17:48 +0000, Thomas Hawtin
<usenet@tackline.plus.com> wrote, quoted or indirectly quoted someone
who said :
>Typically a Java object will keep a single hidden reference to
>information about its class (some JVMs may optimise this away in certain
>situations).
How did you discover that?
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
| |
| Boris Gorjan 2006-02-21, 7:03 pm |
| Roedy Green wrote:
> On Mon, 20 Feb 2006 12:45:02 +0100, Boris Gorjan <borigor@hotmail.com>
> wrote, quoted or indirectly quoted someone who said :
>
>
> Does virtuality fluff up the class file? Does each method explicitly
> name its super-method? I don't think there would be any need to.
Maybe not. I don't know. But there's certainly a difference, say, in C++. IIRC,
runtime must have an additional pointer to a method, if it's virtual.
> The loader can sort all that out from the attributes of the methods.
| |
| Roedy Green 2006-02-21, 7:03 pm |
| On Tue, 21 Feb 2006 16:08:35 +0100, Boris Gorjan <borigor@hotmail.com>
wrote, quoted or indirectly quoted someone who said :
>Maybe not. I don't know. But there's certainly a difference, say, in C++. IIRC,
>runtime must have an additional pointer to a method, if it's virtual.
Java class files are not like object or exe files. The links are not
yet built. Everything is still a big list of symbols. You might java
does a incremental link on every class load.
You may also be concerned with overhead of various hidden tables the
run time has to build to satisfy all this.
Bjarne Stroustrup explained how vtbl's work in C++ which is likely how
they work in Java.
For each class there is a table indexed by method number in the class.
When you override a class, you use the same method numbers on both the
base class and subclas for the methods they have in common. The table
points to the actual code to implement that class's version of it. If
you don't override the method, the entry points directly to whatever
the super class is using for that method.
In each object is a pointer to it's class's vtbl.
Now to dispatch a virtual method, you follow the object's pointer to
the vtbl for its class (hoplefully cached in a register), index by
method number and jump there, all pretty darn quick.
For a static method you can burn the absolute address of the code
right into the call, so it goes direct, bypassing the vtbl. the
address won't change. I don't think code is ever moved once loaded.
It it were, these static call addresses would have to be patched.
for an interface call, it is much hairier. The problem is the
methods implementing the interface live at different offsets in
different classes. You can't use the standard vtbl to find the code..
You say then, why not a separate vtbl for every interface a class
implements that points directly to the code, so it would not matter
what slots they occupy in the classes. ok, how then do you find the
corresponding vtbl given the interface and class. You need some sort
of hashed lookup by class and interface to find the vtbl. You are not
going to reserve a pointer in every possible object to every possible
interface it used, and even if you did, how would you calculate which
pointer to use unless every object has a pointer for every conceivable
interface.
I once thought of implementing this with a giant matrix indexed by
class number and interface number to get you the corresponding vtbl.
The table has to be impractically huge. You could collapse the matrix
to some extent by reusing interface numbers where you have disjoint
sets of classes and interfaces. Of course every time you load a class
you have to maintain this ruddy thing.
Arrghh. Apparently there are some reasonably efficient solutions, the
interface call is obviously much more difficult than a simple virtual
method invocation. This is partly why I feel uneasy at people using
Interface references so routinely, even when there is no benefit from
it.
I think it was handled originally my embedding a list of possible
classes the object turned out to be in past history, with a list of
pre-resolved addresses next to them. So it just did a short linear
search and picked the address matching the class the object was. If
there as no match, it did some great dithery thing to find one then
put that in the tiny cache attached to the call point, for future
reference.
IRRC someone has invented a better way. I don't know how it works.
The Eiffel peopl have had mulitple inheritance since day one, which is
a similar problem to implementing interfaces method calls.. Perhaps
their literature has efficient solutions.
It is partly a general dislike for using things I don't understand
even vaguely in principle that makes me queasy about interfaces.
I suppose the question could be solved with some sort of 32-bit
machine language trace to watch an interface call in action. It can't
be more than a dozen machine instuctions.
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
|
|
|
|
|