Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Assessing Java object size in Matlab

January 29, 2014 No Comments

Have you noticed that all Java object references are displayed as using 0 bytes in the Matlab Workspace browser and the whos function? This is not a bug, but in fact a deliberate design decision, in order to avoid the need to calculate the deep-memory usage of Java references (i.e., objects that include references to other objects etc.).
Well, sometimes it so happens that we really need to know the size of the Java object, or the size difference between two objects (to help resolve memory leaks, for example). There are several resources online that explain how to do this in Matlab (examples 1, 2, 3). Today I will show two alternatives that I found useful within the context of Matlab:

  • ObjectProfiler
  • Classmexer

ObjectProfiler

A full decade ago, Vladimir Roubtsov posted a very detailed article in the JavaWorld magazine explaining how to profile and report Java object sizes. The article contained a downloadable Java archive that we can easily use in Matlab. After downloading the zip file, extract the contained objectprofiler.jar file, add it to the Java classpath and start using it, as follows:

>> javaaddpath 'C:\path\to\where\you\placed\your\copy\of\objectprofiler.jar'
>> com.vladium.utils.ObjectProfiler.sizeof(java.awt.Color.red)
ans =
    28

>> javaaddpath 'C:\path\to\where\you\placed\your\copy\of\objectprofiler.jar' >> com.vladium.utils.ObjectProfiler.sizeof(java.awt.Color.red) ans = 28

Note that the reported sizes may be different on different Matlab releases (=JVM versions) and platforms. Also note that the reported size (28 bytes for the Java Color object) is much smaller than the size required to serialize the object into a byte stream (408 bytes in this case), as I’ve shown in last week’s article.
Running the sizeof method on deeply referenced objects could quickly exhaust Matlab’s memory:

>> jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
% on R2012a: takes a long time and finally reports
>> com.vladium.utils.ObjectProfiler.sizeof(jDesktop)
ans =
    72011200
% on R2014a: takes a long time and finally croaks
% (which is not surprising, considering the Desktop's new toolstrip)
>> com.vladium.utils.ObjectProfiler.sizeof(jDesktop)
Java exception occurred:
java.lang.OutOfMemoryError: Java heap space
	at java.util.IdentityHashMap.resize(Unknown Source)
	at java.util.IdentityHashMap.put(Unknown Source)
	at com.vladium.utils.ObjectProfiler.computeSizeof(ObjectProfiler.java:329)
	at com.vladium.utils.ObjectProfiler.sizeof(ObjectProfiler.java:85)

ObjectProfiler has a very handy feature of enabling a visual display of the object’s reference tree. For example:

>> jObject = java.util.Hashtable
jObject =
{}
>> com.vladium.utils.ObjectProfiler.sizeof(jObject)
ans =
   105
>> com.vladium.utils.ObjectProfiler.profile(jObject).dump
ans =
  105 -> <INPUT> : Hashtable
    60 (57.1%) -> Hashtable#table : Hashtable$Entry[]
      60 (57.1%) -> <shell: Hashtable$Entry[], length=11>
    45 (42.9%) -> <shell: 6 prim/4 ref fields>
>> jObject.put('key1',1.23);
>> com.vladium.utils.ObjectProfiler.sizeof(jObject)
ans =
   189
>> com.vladium.utils.ObjectProfiler.profile(jObject).dump
ans =
  189 -> <INPUT> : Hashtable
    144 (76.2%) -> Hashtable#table : Hashtable$Entry[]
      84 (44.4%) -> Hashtable#table[4] : Hashtable$Entry
        44 (23.3%) -> Hashtable$Entry#key : String
          24 (12.7%) -> String#value : char[]
            24 (12.7%) -> <shell: char[], length=4>
          20 (10.6%) -> <shell: 2 prim/1 ref fields>
        24 (12.7%) -> <shell: 1 prim/3 ref fields>
        16 (8.5%) -> Hashtable$Entry#value : Double
          16 (8.5%) -> <shell: 1 prim/0 ref fields>
      60 (31.7%) -> <shell: Hashtable$Entry[], length=11>
    45 (23.8%) -> <shell: 6 prim/4 ref fields>

As we can see, adding the 'key1' key to the hashtable object actually added 2 new references: a 44-byte String and a 16-byte Double, plus 24 additional overhead bytes, for a total addition of 84 bytes.
ObjectProfiler has a convenience method sizedelta(jObject1,jObject2) which returns the size delta in bytes between the two specified objects. There are a few additional methods for ObjectProfiler and the ObjectProfiler.profile() object – interested readers are referred to the original article and to the source code (which is included within the zip file that we downloaded).

Classmexer

The Classmexer utility works a bit differently but is also very easy to use once the initial setup is done. First we need to download the zip file, then extract the classmexer.jar and place it in your Matlab’s startup folder. In that same folder, edit (create if necessary) a java.opts file with the following line:

-javaagent:classmexer.jar

-javaagent:classmexer.jar

After restarting Matlab, we can use Classmexer as follows:

>> com.javamex.classmexer.MemoryUtil.deepMemoryUsageOf(java.awt.Color.red)
ans =
    32
>> jObject = java.util.Hashtable;
>> com.javamex.classmexer.MemoryUtil.deepMemoryUsageOf(jObject)
ans =
   120
>> jObject.put('key1',1.23); jObject
jObject =
{key1=1.23}
>> com.javamex.classmexer.MemoryUtil.deepMemoryUsageOf(jObject)
ans =
   264

>> com.javamex.classmexer.MemoryUtil.deepMemoryUsageOf(java.awt.Color.red) ans = 32 >> jObject = java.util.Hashtable; >> com.javamex.classmexer.MemoryUtil.deepMemoryUsageOf(jObject) ans = 120 >> jObject.put('key1',1.23); jObject jObject = {key1=1.23} >> com.javamex.classmexer.MemoryUtil.deepMemoryUsageOf(jObject) ans = 264

Note how the values reported by Classmexer differ from those of ObjectProfiler. To tell the truth, I’m not sure which of them to believe: ObjectProfiler seems more detailed, but Classmexer uses Java’s preferred mechanism of using an instrumentation agent.

Related resources

We can also use java.lang.Runtime.getRuntime‘s methods (maxMemory(), freeMemory() and totalMemory()) to monitor overall Java memory (note a MathWorks blog article on this). Note that this reports the total memory values, and fluctuates (sometimes dramatically) from second to second, as Matlab’s desktop and other Java-heavy tools create Java objects, which the JVM garbage-collects.
Jeff Gullet has suggested to monitor these values and programmatically activate a synchronous Java garbage-collection when the memory appears too “crowded” (I fixed Jeff’s posted idea in the snippet below):

r = java.lang.Runtime.getRuntime;
if (r.freeMemory/r.totalMemory) < 0.1
    r.gc();
end

r = java.lang.Runtime.getRuntime; if (r.freeMemory/r.totalMemory) < 0.1 r.gc(); end

A MathWorks technical article provided some assistance on using the JConsole utility to profile Java memory in Matlab. We can also use the JMap and JHat utilities. All these utilities are part of the free Java Development Kit (JDK) that can be downloaded online, just ensure you’re using the same Java version as reported by Matlab:

>> version -java
ans =
Java 1.7.0_11-b21   % i.e., Java 7 update 11

>> version -java ans = Java 1.7.0_11-b21 % i.e., Java 7 update 11

In addition to the JDK tools, I find the open-source JVisualVM utility informative and easy to use. We can also use JMP (R2007a and earlier), TIJMP (R2007b and later), or other 3rd-party tools. A list of Java-centric resources is available in the Java SE Troubleshooting guide.
To complete the picture, a couple of years ago I posted an article on profiling Matlab’s memory usage, which included a section on Java memory. You may also find useful another article I wrote, on finding and fixing a Java memory leak in Matlab.

Related posts:

  1. FindJObj – find a Matlab component's underlying Java object – The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
  2. Matlab callbacks for Java events in R2014a – R2014a changed the way in which Java objects expose events as Matlab callbacks. ...
  3. Matlab callbacks for Java events – Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...
  4. Using pure Java GUI in deployed Matlab apps – Using pure-Java GUI in deployed Matlab apps requires a special yet simple adaptation. ...
  5. Matlab-Java memory leaks, performance – Internal fields of Java objects may leak memory - this article explains how to avoid this without sacrificing performance. ...
  6. New book: Undocumented Secrets of MATLAB-Java Programming – Undocumented Secrets of Matlab-Java Programming (ISBN 9781439869031) is a book dedicated to the integration of Matlab and Java. ...
Java Memory
Print Print
« Previous
Next »
Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitable (6) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top