miércoles, 28 de diciembre de 2011

Diagnosing Java memory leaks (OutOfMemoryError)

  • First you have to get a Heap Dump.
  • To analize it, IBM Heap Analyzer is the way to go.
  • IBM Heap Analyzer's Tree View *is* the way to go.
  • Hopefully you'll have one big tree. Go for it!
  • Descend fast while the big percentage doesn't change. Ignore "interesting" objects if the percentage doesn't change under them.
  • If you find a ClassLoader in the way, ignore the history behind you. Keep descending.
  • Descend more.
  • Be aware of "infinite chains" of the same objects or "infinite chains" with patterns of the same objects.
  • Be aware of gaps in the percentage.
  • Keep in mind that the tree Heap Analzyer is just a way to show you the memory. You have thousands of ways to draw an analogous tree. Each point in the tree can have several "parents". Heap Analyzer is only showing you one of them.
References:

jueves, 22 de diciembre de 2011

Programmatically obtaining "Messages waiting for read" for OC4J 10g JMS memory topic using JMX

You have to configure your classpath with the following jars (I haven´t test which of them are extrictly necessary):
  • adminclient.jar
  • dms.jar
  • ejb.jar
  • javax77.jar
  • jms.jar
  • oc4jclient.jar
  • oc4j-internal.jar
  • optic.jar
  • pcl.jar

Although I'm working with OAS and not with OC4J standalone, I'll connect directly to the OC4J instance (not through OPMN). So I'll use this type of URL: service:jmx:rmi://[server]:[oc4j_rmi_port]. I just need to get the OC4J RMI port usign opmnctl -l.

Obtain the connection using the oc4jadmin credentials:

JMXServiceURL url = new JMXServiceURL(makeJmxUrl());
String[] creds = { "oc4jadmin", oc4jadminPassword };
Map<String, Object> env = new HashMap<String, Object>();
env.put(JMXConnector.CREDENTIALS, creds);
JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();


The JMS topic I'm trying to obtain the statistics from is one of the Oracle ESB 10g standard topics: ESB Java Deferred. I have several subscribers and each one of them has a corresponding MBean. The statistics are presented from each one of them, and not as totals for the topic. So, if for example, I want to get the "Messages waiting for read" for the topic, I have to obtain the value for each subscriber and add them. The wildarded URL to obtain the MBeans for the subscribes is as follows: oc4j:j2eeType=JMSStoreResource,*,JMSDestinationResource=\"Topic.ESB Deferred Topic\",JMSResource=\"JMS\",J2EEServer=standalone

ObjectName mbeanNameQueryPattern = new ObjectName("oc4j:j2eeType=JMSStoreResource,*,JMSDestinationResource=\"Topic.ESB Deferred Topic\",JMSResource=\"JMS\",J2EEServer=standalone");
Set<ObjectName> mbeansNames = mbsc.queryNames(mbeanNameQueryPattern, null);

Iterate over the MBeans to obtain their statistics: There are several statistics to choose (messageCommitted, messageRolledBack, messageCount -Messages waiting for read-, messageDequeued -Messages waiting for commit-, messageEnqueued, messageDiscarded, messageExpired, messagePagedIn, messagePagedOut, messageRecovered and pendingMessageCount), but right now I'm only getting this: messageCount.

long value = 0L;
Iterator mbeansNamesIter = mbeansNames.iterator();
while (mbeansNamesIter.hasNext()) {
    ObjectName mbeanName = mbeansNamesIter.next();
    JMSStoreStatsImpl jmsStats = (JMSStoreStatsImpl)mbsc.getAttribute(mbeanName, "stats");
    CountStatisticImpl countStatistic = (CountStatisticImpl)jmsStats.getStatistic(statisticName);
    value = value + countStatistic.getCount();
}

Thos are the related imports:

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import oracle.oc4j.admin.management.shared.statistic.CountStatisticImpl;
import oracle.oc4j.admin.management.shared.statistic.JMSStoreStatsImpl;

JVM must be started with this flag: -Djmx.remote.protocol.provider.pkgs=oracle.oc4j.admin.jmx.remote

If you want to make a "real time" desktop chart with the values, there's a very nice and easy alternative: VisualVM's charting API. Here is an example.


"Error creating managed object for class org.jboss.weld.servlet.WeldListener"

Following the Arun Gupta's Java EE 6 Hands-on Lab using Netbeans 7.0.1 and Glassfish 3.1.1, I found the following error, which prevented me from deploy the app: Error creating managed object for class org.jboss.weld.servlet.WeldListener.

I just restarted Glassfish, did a Clean and Build and the problem was gone :P

The Lab is a very good way to know several new cool Java EE 6 features.