Monday, September 19, 2022

Ten Java coding antipatterns to avoid: Worst practices #10 through #6

You should avoid these worst practices—and fix them when you maintain or refactor existing code.


With experience, everyone gains ideas of good and bad practice, and that applies to both coding and code reviews. In her article “Five code review antipatterns,” fellow Java Champion Trisha Gee pointed out several worst practices for the code review process. I’d like to point out 10 antipatterns for the coding process itself; half are in this article, and the worst offenders are in the next article, to be published in Java Magazine soon.

Oracle Java, Java Tutorial and Materials, Oracle Java Certification, Java Prep, Oracle Java Preparation

To be clear, you should avoid these worst practices—and eliminate them when you maintain or refactor existing code. And, of course, resolve them if you see these issues during a code review.

Worst practice #10: Import messes


The list of imported classes and methods at the top of a class is intended to be a reference to the API that it is using. Imports ending in * convey little specific information and, even worse, unused imports are misleading. Imports in a quasi-random order take longer to read, which is a pain for maintenance.

A better way: Let your IDE maintain the imports. The Eclipse IDE has really good support for this: Its “organize imports” feature will, with one click, remove unused imports, add any missing imports, and sort the list into a consistent order, with java classes first, then javax, then third-party classes, and then static imports. You can get all that in IntelliJ IDEA, but you must tweak three or four settings to get there.

True confession: When I was a young and foolish tech lead on a large app project which shall remain nameless, I once set the messaging level for unused imports from Warning to Error in the Eclipse settings and committed this to the project repository. Of course, I did this worst practice only after lecturing and hectoring the development team didn’t work. This was part of my plan to keep imports organized across the entire project. Changing this setting wasn’t popular, but the few opposing developers came around after seeing how easy it was to fix (using Ctrl+Shift+O) and how this change made the long list of imports on that project much easier to read.

Worst practice #9: Inconsistent indentation


The indentation-champion language is surely Python, which uses indentation instead of braces or keywords to denote the body of a control flow or method. Thus, if Python code is indented incorrectly it won’t compile!

Fortunately, Java (like the other C-family languages) uses braces for block structure and ignores whitespace. That said, consistent indentation still matters. While indents are not required by the compiler, they are required for the human reader. Consider the following code:

if (condition)
    statement1;
    statement2;
statement3;

Upon a quick read, it appears as though statements 1 and 2 are controlled by the if. However, statement 2 is not, because this is Java, not Python.

Or consider the following code:

statement1;
   statement2;
 statement3;

What was the programmer thinking? The code looks like something spewed by a waterfall on a windy day. The statements have the same level of control flow, so they should all begin in the same column. Again, modern IDEs can repair this damage in no time flat with a feature such as “Fix Indentation.”

Select an entire file with Ctrl+A or Cmd+A, or select one method by selecting it with the mouse. Then choose the indentation repair from the Edit or Code menu. Problem solved!

Worst practice #8: JAR files without links


When Java first arrived, it appeared that it would solve one of Windows developers’ nightmares: the oft-cursed “DLL Hell,” where a mixture of different shared objects (such as .dll files in Windows or .so files on other platforms) contain version conflicts.

Unfortunately, the problem wasn’t solved. That’s part of what the Java Platform Module System (JPMS) was intended to address. Tools such as Maven and Gradle have been helping with this issue for years—but sometimes JAR files without links still appear.

The worst case I’ve run across is a project with a folder of files that were named something like the following:

util.jar
system.jar
financial.jar
report.jar

The files had dates about 10 years old. Each of the four projects had been updated by their maintainers during that time, but there was no record of what version of the library JAR files was depended upon by the main application—unless you considered “the JAR files that happen to be in the lib folder” to be a form of documentation.

Some of the JAR files were from third-party APIs (whose names have been changed to protect the guilty) that had multiple news-making security issues over the years, yet none of the developers on the team seemed concerned enough to move to versioned JAR files—maybe because they didn’t know if they were using the affected versions.

I admit that I may have created some projects like this many years ago—but I have taken the pledge to avoid them.

Today all my projects are managed by Maven or Gradle, each of which takes a specification of each dependency’s group (usually the organization), artifact (the JAR name), and a version number and will fetch the matching JAR file. That file will have the artifact name and version number in the filename. For example, a project might have the following in its Maven configuration file (pom.xml):

<dependency>
    <groupId>com.darwinsys</groupId>
    <artifactId>darwinsys-api</artifactId>
    <version>1.7.5</version>
</dependency>

This code in pom.xml directs Maven to download the darwinsys-api-1.7.5.jar file and store it (along with some metadata files) in a carefully constructed tree in my home directory (which is ~/.m2/repository/com/darwinsys/darwinsys-api/1.7.5). In this way, when two or more projects require the same JAR file, the JAR will be downloaded only once.

Here is a very selective look at the Maven local repository on one of my systems.

$ ls ~/.m2/repository
aopalliance biz bouncycastle cglib com dev eclipse edu info io
jakarta javax jaxen jline log4j ...
$ ls ~/.m2/repository/com/darwinsys/darwinsys-api
1.5.14
1.5.15
1.7.5
maven-metadata-central.xml
maven-metadata-central.xml.sha1
resolver-status.properties
$ ls ~/.m2/repository/com/darwinsys/darwinsys-api/1.7.5
_remote.repositories
darwinsys-api-1.7.5.jar
darwinsys-api-1.7.5.jar.sha1
darwinsys-api-1.7.5.pom
darwinsys-api-1.7.5.pom.sha1
$

By looking at the pom.xml file, not only is it clear which version of the API is used in that particular project, it’s also clear (at least if you know what the default is and that there is no other repository listed in the pom.xml file) that the JAR file came from the centralized Maven repository, Maven Central.

What’s more, the JAR file itself has its version number embedded in its filename.

Maven uses the Secure Hash Algorithm (sha) files to ensure that the JAR file hasn’t been tampered with. If you run the build tool in debug mode, you will see an extremely verbose output that includes the full path of each JAR file that is on the classpath. Plus, Maven has capabilities such as mvn dependency:tree to show all the sub- and sub-sub-dependencies in a tree format.

Keeping JAR dependencies under control is part of making software development a discipline. Make it so!

Worst practice #7: Meaningless names


Now is a good time to quote Ian’s First Rule of Coding:

You should never type more than a few characters of any name except when you’re creating it.

Given that most developers (except for two or three vi diehards) use a full-featured IDE these days, and since all major IDEs have really good code completion features, there’s no reason to type out long names.

But neither is there any reason to avoid giving meaningful names to methods, fields, classes, variables, and other elements.

Variable names such as i, j, and k are, in my book, allowed only when you’re using the old-style for loop to index an array or count something. Also allowed are names such as s for a locally used String, in the header of a few-lines-long method, or when you’re writing a lambda that is short and self-contained.

For everything else, pick a useful name.

This becomes particularly important where the var keyword is used to avoid having to give type declarations. Why? The variable name may be the only clue the reader has as to what you mean the variable to be used for. Consider the following example:

for (int i = 0; i < functionData.length; i++) {
        functionData[i] = someFunction(i);
}

customerNames.forEach(s->s.substring(1)); // "s" OK here

int bodyFontSize = 11;

I’m not only talking about variables: Method names should also be meaningful. In writing JUnit tests, you’ll find that names like test1() and test2() and so on are not only useless: They mislead, because such naming implies an ordering that isn’t there.

JUnit does not make any claim to run methods in the order in which you wrote them. Methods are, in fact, run in the order given by the reflection API, which is documented to return members that “are not sorted and are not in any particular order.”

Here is an example of this antipattern.

@Test
    public void test1() {   // Bad
        // test here...
    }

And here is a better way to write it.

@Test
    public void testPositiveResultsCorrect() { // Better
        // test here...
    }

Remember: You are one of the people most likely to need to read this code months or years after you wrote it, so be kind to yourself!

Worst practice #6: Reinventing the flat tire


This antipattern’s title is from a paper I worked on many years ago. “Reinventing the wheel” is a common English-language idiom for designing and creating something that already exists. My then-colleague Geoff Collyer and I took the expression one step further, in a C coding style paper Geoff and I co-wrote long ago in a galaxy far away. “Reinventing the flat tire” meant that a programmer not only wrote code whose functionality was readily available in a standard or common library, but that the new code did a worse job than the public API.

Here’s an example of this antipattern.

String[] candidates = getStrings();
String searchingFor = "The Lost Boys";
int found = -1;
for (int i = 0; i < candidates.length; i++) { // flat tire
    if (candidates[i].equals(searchingFor)) {
        found = i;
    }
}

And here is a better way.

Arrays.sort(candidates); // start of "better" approach
found = Arrays.binarySearch(candidates, searchingFor);

You might think the second approach would run more slowly, because a binary search requires the input be sorted. That’s true. But notice that the programmer of the antipattern forgot to break out of the loop when finding the match, so that code’s efficiency is terrible anyway.

Reinventing public APIs is nothing new and is often a sign of incomplete knowledge of the API. Of course, it’s easy enough to make that error when languages have such a vast standard library as Java has.

Here’s an example of reinventing an API you might or might not know; this has been in the platform since Java 1.7.

var x = getValue();     // legacy way
if (x == null) {
    x = getSomeDefaultValue();
}
System.out.println(x);

Here’s the better, shorter way.

var y = Objects.requireNonNullElse(getValue(), getSomeDefaultValue());
System.out.println(y);

The first example’s programmer could have used the standard Objects.requireNonNullElse() library routine, which has a variety of overloads that will help reduce coding for some common operations.

Source: oracle.com

Friday, September 16, 2022

Chaos Engineering – Metaspace OutOfMemoryError

JVM memory has following regions:

Chaos Engineering, Oracle Java Certification, Oracle Java Career, Java Skills, Java Jobs, Java Tutorial and Materials

a. Young Generation

b. Old Generation

c. Metaspace

d. Others region

When you encounter ‘java.lang.OutOfMemoryError: Metaspace’ it indicates that the Metaspace region in the JVM memory is getting saturated. Metaspace is the region where metadata details that are required to execute your application are stored. In nutshell they contain Class definitions and method definitions of your application. To learn more about what gets stored in each of the JVM memory regions, you may refer to this video clip. In this post let’s discuss how one can simulate java.lang.OutOfMemoryError: Metaspace.

Simulating java.lang.OutOfMemoryError: Metaspace


To simulate ‘java.lang.OutOfMemoryError: Metaspace’, we wrote this program:

public class MetaspaceLeakProgram {
    
   public static void main(String[] args) throws Exception {
         
      ClassPool classPool = ClassPool.getDefault();
 
      while (true) {
             
         // Keep creating classes dynamically!
         String className = "com.buggyapp.MetaspaceObject" + UUID.randomUUID();
         classPool.makeClass(className).toClass();
      }
   }    
}

This program leverages the ‘ClassPool’ object from the opensource javassist library. This ‘ClassPool’ object is capable of creating new classes at runtime. Please take a close look at the above program. If you notice, this program keeps on creating new classes. Below is the sample class names generated by this program:

Chaos Engineering, Oracle Java Certification, Oracle Java Career, Java Skills, Java Jobs, Java Tutorial and Materials

com.buggyapp.MetaspaceObject76a9a309-c9c6-4e5f-a302-8340eb3acdef
com.buggyapp.MetaspaceObjectb9bd6832-bacd-4c7c-a6e6-3bfa19a85e80
com.buggyapp.MetaspaceObject81d9d086-7245-4304-818f-0bfcbf319fd3
com.buggyapp.MetaspaceObjecte27068b6-f4cb-498a-80d5-0e5b61c2ada0
com.buggyapp.MetaspaceObject06f9d773-d365-48c8-a5cc-9c69b3178f4c
:
:
:

Whenever a new class is created, its corresponding class metadata definitions are created in the JVM’s Metaspace region. Since metadata definitions are created in Metaspace, it’s size starts to grow. When the maximum metaspace size is reached, application will experience ‘java.lang.OutOfMemoryError: Metaspace’

java.lang.OutOfMemoryError: Metaspace causes


 ‘java.lang.OutOfMemoryError: Metaspace’ error happens because of two reasons:

 a. Metaspace region size is under allocated 

 b. Memory leak in the Metaspace region. 

You can address #a by increasing Metaspace region size. You can do this by passing the JVM argument ‘-XX:MaxMetaspaceSize’. 

In order to address #b, you have to do proper troubleshooting. Here is a post which walks through how to troubleshoot memory leaks in the Metaspace region.

Source: javacodegeeks.com

Wednesday, September 14, 2022

Monitoring WebLogic Server for Oracle Container Engine for Kubernetes

How to use open source tools to keep tabs on enterprise applications

 
Everyone should monitor their production system to understand how the system is behaving. Monitors help you understand the workloads and ensure you get notifications when something fails—or is about to fail.

In Java EE applications, you can choose to monitor many metrics on your servers that will identify workloads and issues with applications. For example, you could monitor the Java heap, active threads, open sockets, CPU utilization, and memory usage.

If you have a Java EE application deployed to Oracle WebLogic Server for Oracle Cloud Infrastructure Container Engine for Kubernetes, this article is for you.

Oracle WebLogic Server for Oracle Cloud Infrastructure Container Engine for Kubernetes can help you quickly create Oracle WebLogic configurations on Oracle Cloud, for example, to allocate network resources, reuse existing virtual cloud networks or subnets, configure the load balancer, integrate with Identity Cloud Manager, or configure Oracle Database.

In this article, I’ll show you how to use two open source tools—Grafana and Prometheus—to monitor an Oracle WebLogic domain deployed in Oracle WebLogic Server for Oracle Cloud Infrastructure Container Engine for Kubernetes.

By the way, this procedure will use several Helm charts to walk through the individual steps required to install and configure Prometheus and Grafana. For your own deployment, it is up to you to create a single Helm chart to deploy Prometheus or Grafana.

Prerequisites


Before you get started, you should have installed at least one of these Oracle Cloud Marketplace applications. (UCM refers to the Universal Credits model; BYOL stands for bring your own license.)


Deploy WebLogic Monitoring Exporter to your Oracle WebLogic domain


Here are the step-by-step instructions.

1. Open a terminal window and access the administration instance that is created with Oracle WebLogic Server for Oracle Cloud Infrastructure Container Engine for Kubernetes. You can see detailed instructions here.

2. Go to the root Oracle Cloud Infrastructure File Storage Service folder, which is /u01/shared.

cd /u01/shared

3. Download the WebLogic Monitoring Exporter war file from GitHub into the wlsdeploy folder.

wget https://github.com/oracle/weblogic-monitoring-exporter/releases/download/v2.0.0/wls-exporter.war -P wlsdeploy/applications

4. Include the sample exporter configuration file.

zip -r weblogic-exporter-archive.zip wlsdeploy/

wget https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/master/samples/kubernetes/end2end/dashboard/exporter-config.yaml -O config.yml
zip wlsdeploy/applications/wls-exporter.war -m config.yml

5. Create a WebLogic Server Deploy Tooling archive where you’ll place the weblogic-exporter-archive.war file.

zip -r weblogic-exporter-archive.zip wlsdeploy/

6. Create a WebLogic Server Deploy Tooling model to deploy the WebLogic Monitoring Exporter application to your domain.

ADMIN_SERVER_NAME=$(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.wls_admin_server_name')
DOMAIN_CLUSTER_NAME=$(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.wls_cluster_name')

cat > deploy-monitoring-exporter.yaml << EOF
appDeployments:
  Application:
    'wls-exporter' :
      SourcePath: 'wlsdeploy/applications/wls-exporter.war'
      Target: '$DOMAIN_CLUSTER_NAME,$ADMIN_SERVER_NAME'
      ModuleType: war
      StagingMode: nostage
EOF

7. Deploy the WebLogic Monitoring Exporter application to your domain using the Pipeline update-domain screen.

8. From the Jenkins dashboard, open the Pipeline update-domain screen and specify the parameters, as follows (and see Figure 1):

◉ For Archive_Source, select Shared File System.
◉ For Archive_File_Location, enter /u01/shared/weblogic-exporter-archive.zip.
◉ For Domain_Model_Source, select Shared File System.
◉ For Model_File_Location, enter /u01/shared/deploy-monitoring-exporter.yaml.

Figure 1. The Pipeline update-domain parameters screen

Then click the build button. To verify that the deployment is working, run the following commands:

INGRESS_NS=$(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.ingress_namespace')
SERVICE_NAME=$(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.service_name')
WLS_CLUSTER_URL=$(kubectl get svc "$SERVICE_NAME-external" -n $INGRESS_NS -ojsonpath="{.status.loadBalancer.ingress[0].ip}")

The output should look something like the following:

[opc@wlsoke-admin ~]$ curl -k https://$WLS_CLUSTER_URL/wls-exporter
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Weblogic Monitoring Exporter</title>
</head>

Create PersistentVolume and PersistentVolumeClaim for Grafana, Prometheus Server, and Prometheus Alertmanager

Oracle WebLogic Server for Oracle Cloud Infrastructure Container Engine for Kubernetes creates a shared file system using Oracle Cloud Infrastructure File Storage Service, which is mounted across the different pods running in the Oracle Container Engine for Kubernetes cluster and the administration host. To store data on that shared file system, the next step is to create subpaths for Grafana and Prometheus to store data.

This procedure will create a Helm chart with PersistentVolume (PV) and PersistentVolumeClaim (PVC) for Grafana, Prometheus Server, and Prometheus Alertmanager. This step doesn’t use the Prometheus and Grafana charts for creating the PVC because those don’t yet support Oracle Cloud Infrastructure Container Engine for Kubernetes with Oracle Cloud Infrastructure File Storage Service.

1. Open a terminal window and access the administration instance that is created with Oracle WebLogic Server for Oracle Cloud Infrastructure Container Engine for Kubernetes.

2. Create folders for monitoringpv and templates. You’ll place the Helm chart here.

mkdir -p monitoringpv/templates

3. Create the Chart.yaml file in the monitoringpv folder.

cat > monitoringpv/Chart.yaml << EOF
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for creating pv and pvc for Grafana, Prometheus and Alertmanager
name: monitoringpv
version: 0.1.0
EOF

4. Similarly, create the values.yaml file required for the chart using the administration instance metadata.

cat > monitoringpv/values.yaml << EOF
exportpath: $(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.fss_export_path')
classname: $(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.fss_chart_name')
serverip: $(kubectl get pv jenkins-oke-pv -o jsonpath='{.spec.nfs.server}')
EOF

5. Create the target folders on the shared file system.

mkdir /u01/shared/alertmanager
mkdir /u01/shared/prometheus
mkdir /u01/shared/grafana

6. Create template files for PV and PVC for Grafana, Prometheus Server, and Prometheus Alertmanager.

cat > monitoringpv/templates/grafanapv.yaml << EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-grafana
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 10Gi
  mountOptions:
  - nosuid
  nfs:
    path: {{ .Values.exportpath }}{{"/grafana"}}
    server: "{{ .Values.serverip }}"
  persistentVolumeReclaimPolicy: Retain
  storageClassName: "{{ .Values.classname }}"
  volumeMode: Filesystem
EOF

cat > monitoringpv/templates/grafanapvc.yaml << EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-grafana
  namespace: monitoring
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: "{{ .Values.classname }}"
  volumeMode: Filesystem
  volumeName: pv-grafana
EOF

cat > monitoringpv/templates/prometheuspv.yaml << EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-prometheus
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 10Gi
  mountOptions:
  - nosuid
  nfs:
    path: {{ .Values.exportpath }}{{"/prometheus"}}
    server: "{{ .Values.serverip }}"
  persistentVolumeReclaimPolicy: Retain
  storageClassName: "{{ .Values.classname }}"
  volumeMode: Filesystem
EOF

cat > monitoringpv/templates/prometheuspvc.yaml << EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-prometheus
  namespace: monitoring
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: "{{ .Values.classname }}"
  volumeMode: Filesystem
  volumeName: pv-prometheus
EOF

cat > monitoringpv/templates/alertmanagerpv.yaml << EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-alertmanager
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 10Gi
  mountOptions:
  - nosuid
  nfs:
    path: {{ .Values.exportpath }}{{"/alertmanager"}}
    server: "{{ .Values.serverip }}"
  persistentVolumeReclaimPolicy: Retain
  storageClassName: "{{ .Values.classname }}"
  volumeMode: Filesystem
EOF

cat > monitoringpv/templates/alermanagerpvc.yaml << EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-alertmanager
  namespace: monitoring
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: "{{ .Values.classname }}"
  volumeName: pv-alertmanager
EOF

7. Install the monitoringpv Helm chart you created.

helm install monitoringpv monitoringpv --create-namespace --namespace monitoring --wait

8. Verify that the output looks something like the following:

[opc@wlsoke-admin ~]$ helm install monitoringpv monitoringpv --namespace monitoring --wait
NAME: monitoringpv
LAST DEPLOYED: Wed Apr  15 16:43:41 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

Install the Prometheus Helm chart

These instructions are a subset of those in the Prometheus Community Kubernetes Helm Charts GitHub project. Do these steps in the same terminal window where you accessed the administration instance created with Oracle WebLogic Server for Oracle Cloud Infrastructure Container Engine for Kubernetes:

1. Add the required Helm repositories.

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add kube-state-metrics https://kubernetes.github.io/kube-state-metrics
helm repo update

At this time, you could optionally inspect all of Helm’s available configurable options by showing Prometheus’ values.yaml file.

helm show values prometheus-community/prometheus

2. Copy the needed values from the WebLogic Monitoring Exporter GitHub project to the Prometheus directory.

wget https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/master/samples/kubernetes/end2end/prometheus/values.yaml -P prometheus

3. To customize your Prometheus deployment with your own domain information, create a custom-values.yaml file to override some of the values from the prior step.

DOMAIN_NS=$(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.wls_domain_namespace')
DOMAIN_NAME=$(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.wls_domain_uid')
DOMAIN_CLUSTER_NAME=$(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.wls_cluster_name')

cat > prometheus/custom-values.yaml << EOF
alertmanager:
  prefixURL: '/alertmanager'
  baseURL: http://localhost:9093/alertmanager
nodeExporter:
  hostRootfs: false
server:
  prefixURL: '/prometheus'
  baseURL: "http://localhost:9090/prometheus"
extraScrapeConfigs: |
    - job_name: '$DOMAIN_NAME'
      kubernetes_sd_configs:
      - role: pod
      relabel_configs:
      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_pod_label_weblogic_domainUID, __meta_kubernetes_pod_label_weblogic_clusterName]
        action: keep
        regex: $DOMAIN_NS;$DOMAIN_NAME;$DOMAIN_CLUSTER_NAME
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: \$1:\$2
        target_label: __address__
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: pod_name
      basic_auth:
        username: --FIX ME--
        password: --FIX ME--
EOF

4. Open the custom-values.yaml file and update the username and password. Use the credentials you use to log in to the administrative console.

basic_auth:
        username: myadminuser
        password: myadminpwd

5. Install the Prometheus chart.

helm install --wait prometheus prometheus-community/prometheus --namespace monitoring -f prometheus/values.yaml -f prometheus/custom-values.yaml

6. Verify that the output looks something like the following:

[opc@wlsoke-admin ~]$ helm install --wait prometheus prometheus-community/prometheus --namespace monitoring -f prometheus/values.yaml -f prometheus/custom-values.yaml
NAME: prometheus
LAST DEPLOYED: Wed Apr  15 22:35:15 2021
NAMESPACE: monitoring
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
. . .

7. Create an ingress file to expose Prometheus through the internal load balancer.

cat << EOF | kubectl apply -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
  name: prometheus
  namespace: monitoring
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: prometheus-server
          servicePort: 80
        path: /prometheus
EOF

8. The Prometheus dashboard should now be available at the same IP address used to access the Oracle WebLogic Server Administration Console or the Jenkins console but at the /Prometheus path (see Figure 2).

Figure 2. The Prometheus dashboard

Install the Grafana Helm chart

The instructions described here are a subset of those in the Grafana Community Kubernetes Helm Charts GitHub project. As before, do these steps within the same terminal window where you accessed the administration instance created with Oracle WebLogic Server for Oracle Cloud Infrastructure Container Engine for Kubernetes.

1. Add the Grafana charts repository.

helm repo add grafana https://grafana.github.io/helm-charts
helm repo update

2. Create a values.yaml file to customize the Grafana installation.

INGRESS_NS=$(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.ingress_namespace')

SERVICE_NAME=$(curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/ | jq -r '.metadata.service_name')

INTERNAL_LB_IP=$(kubectl get svc "$SERVICE_NAME-internal" -n $INGRESS_NS -ojsonpath="{.status.loadBalancer.ingress[0].ip}")

mkdir grafana

cat > grafana/values.yaml << EOF
persistence:
  enabled: true
  existingClaim: pvc-grafana

admin:
  existingSecret: "grafana-secret"
  userKey: username
  passwordKey: password

grafana.ini:
  server:
    domain: "$INTERNAL_LB_IP"
    root_url: "%(protocol)s://%(domain)s:%(http_port)s/grafana/"
    serve_from_sub_path: true
EOF

3. Create a grafana-secret Kubernetes secret file containing admin credentials for Grafana server (with your own credentials, of course).

kubectl --namespace monitoring create secret generic grafana-secret --from-literal=username=your username --from-literal=password=yourpassword

4. Install the Grafana Helm chart.

helm install --wait grafana grafana/grafana --namespace monitoring -f grafana/values.yaml

5. Verify that the output looks something like the following:

[opc@wlsoke-admin ~]$ helm install --wait grafana grafana/grafana --namespace monitoring -f grafana/values.yaml
NAME: grafana
LAST DEPLOYED: Fri Apr  16 16:40:21 2021
NAMESPACE: monitoring
STATUS: deployed
REVISION: 1
NOTES:
. . .

6. Expose the Grafana dashboard using the ingress controller.

cat <<EOF | kubectl apply -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
  name: grafana
  namespace: monitoring
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: grafana
          servicePort: 80
        path: /grafana
EOF

7. The Grafana dashboard should now be available at the same IP address used to access the Oracle WebLogic Server Administration Console or the Jenkins console and Prometheus but at the /Grafana path (see Figure 3). You should log in with the credentials you configured in the secret file. 

Figure 3. The Grafana login screen

Create the Grafana data source

For this article, I’ll reuse the steps described in the WebLogic Monitoring Exporter sample. You can find the full documentation on how to create Grafana data sources in the Grafana documentation.

1. Once you log in to the Grafana dashboard (as shown in Figure 3), go to Configuration > Data Sources (see Figure 4) and click Add data source to go to the screen where you add the new data source (see Figure 5).

Figure 4. The Configuration menu with the Data Sources option

Figure 5.The screen where you add a new data source

2. Select Prometheus as the data source type (see Figure 6).

Figure 6. Choose Prometheus as the data source type.

3. Set the URL to http://<INTERNAL_LB_IP>/prometheus and click the Save&Test button (see Figure 7).

Important note. INTERNAL_LB_IP is the same IP address you use to access Grafana, Prometheus, Jenkins, and Oracle WebLogic Server Administration Console. You can see how to get that address in this document.

Figure 7. Set the URL for the data source; be sure to use your own IP address.

Import the Oracle WebLogic Server dashboard into Grafana

1. Log in to the Grafana dashboard. Navigate to Dashboards > Manage and click Import (see Figure 8).

Figure 8. The screen for importing a new dashboard

2. Open this JSON code file in a browser. Copy the contents into the Import via panel json section of the dashboard screen and click Load (see Figure 9).

Figure 9. This is where you’ll paste the JSON code.

3. Click the Import button and verify you can see the Oracle WebLogic Server dashboard on Grafana (see Figure 10). That’s it! You’re done!

Figure 10. The Oracle WebLogic Server dashboard running within Grafana

Source: oracle.com

Monday, September 12, 2022

Spring Boot – Difference Between AOP and OOP

Spring Boot, AOP, OOP, Oracle Java Certification, Oracle Java Career, Java Skills, Java Jobs, Java Tutorial and Materials, Java Prep, Java Preparation

AOP(Aspect-Oriented Programming) complements OOP by enabling modularity of cross-cutting concerns. The Key unit of Modularity(breaking of code into different modules) in Aspect-Oriented Programming is Aspect. one of the major advantages of AOP is that it allows developers to concentrate on business logic. It is more convenient to use because changes need to be done in only one place. AOP is used along with spring Ioc to provide a very capable middleware solution.

Note: Cross cutting concerns are one of the concerns in any application such as logging, security, caching, etc. They are present in one part of the program but they may affect other parts of the program too.

Spring Boot, AOP, OOP, Oracle Java Certification, Oracle Java Career, Java Skills, Java Jobs, Java Tutorial and Materials, Java Prep, Java Preparation
AOP is used along with Oop as it also works around classes and objects, etc. We can also say that Oop is a basic term for AOP. Different Frameworks used in Aop are AspectJ, JBoss, and Spring. AOP makes the program loosely coupled. AOP separates business logic from cross-cutting concerns. The aspect class which contains cross-cutting concerns is annotated by @Aspect and @EnableAspectJAutoProxy annotations

AOP has different terms like Aspect, Weaving, different types of advices, JoinPoints and Pointcut expressions, etc. These terms are explained below:

◉ Aspect: The cross-cutting concerns are modularized as Aspect. The classes which contain such cross-cutting concerns are annotated with @Aspect annotation.
◉ Join point: Method execution is represented by using Joinpoint.
◉ Advice: Aspect takes action on a particular Joinpoint. This action depends on various advice which is explained below:
◉ Before advice: It runs before the method execution.
◉ After returning advice: It runs after the result is returned by the method.
◉ After throwing advice: It runs after an exception is thrown by the method.
◉ After (finally) advice: It is executed after method execution or after an exception is thrown or the result is returned by the method.
◉ Around advice: It can perform the behavior before and after the method invocation.
◉ Pointcut: Pointcut is a signature that matches the join points.

Illustration: A pointcut expression with before advice:

// Annotation
@Before("execution(* abc.efg.gettingstarted.dao.*.add(..))")

public void allMethods(Point Point) 
{  // Aspect body }

Object-Oriented Programming


The object-oriented programming model works around classes and objects. The main building blocks of Oop are classes, objects, methods, attributes, etc. Oop has various advantages such as code reusability, flexibility, etc. It also maintains modularity using classes.

Note: Object is an instance of class and class is a blueprint of an object created.

The Key unit of Modularity(breaking of code into different modules) in Object-Oriented Programming is class. Oop contains objects, classes, interfaces, etc. Oop lacks the feature of using cross-cutting concerns. It consists of various concepts such as Data abstraction, Encapsulation, Polymorphism, and Inheritance.

Illustration: If there is a fruit class then apple, orange, banana are various objects of the fruit class.

Source: geeksforgeeks.org

Friday, September 9, 2022

7 Best Plugins For Spring Boot and Java in Eclipse

With the fast-paced technology, every developer wants to build something which requires less time and effort. Being in one of the most growing communities with a count of more than 10 million, developers have to maintain that by working more efficiently. The best plugin you use for your project, the more efficient an application is. Like Python which has uncountable libraries used to build an application, Java has plugins that can be installed in Eclipse to boost productivity and add extra functionalities to the application. Plugins are the smallest, deployable and extensible libraries that contain pieces of code meant for some specific purpose. 

Oracel Java, Oracle Java Tutorial and Materials, Core Java, Java Certification, Oracle Java Career, Java Skills, Java Jobs, Java News, Java Prep, Java Preparation

How to install plugins in your IDE (Eclipse)? The answer is using the marketplace in Eclipse. Eclipse marketplace has provided you with the feature to search for a plugin and its download count in the IDE itself. Eclipse has 1667 plugins available for Spring Boot and Java development. Having too many plugins creates confusion as to which one to choose. We have filtered some of the best plugins which you can use for SpringBoot and Java in Eclipse. Let’s explore them one by one. 

1. EGit

EGit (an Eclipse provider for Git) is one of the best plugins for Java developers. As many of us know that Git is an open-source version control system where every developer can manage and update changes to the source code of the website. When using Eclipse for implementing software, EGit is an essential tool that can be used by developers to perform operations like branching and reverting a single file. This plugin provides rebasing and has streamlined commands to pull/push, synchronize view, support, and read for . git/exclude files. It has multiple views to perform Git actions without knowing git commands.

Features of EGit:

◉ Creating backup is easy

◉ Track and update changes

◉ Git repository cloning to pull, push, merge, commit, etc

2. SonarLint

SonarLint is a free plugin for Eclipse that is primarily responsible for detecting and fixing quality and security issues while writing code. It provides instant feedback on the problems faced in the code during development supporting multiple languages other than Java such as JavaScript, PHP, and Python. Additionally, SonarLint can also be integrated with SonarQube or SonarCloud. SonarLint is used by developers to analyze code, detect errors/bugs, and act as a quality editor. 

Features of SonarLint:

◉ Big picture of all issues

◉ Secure, reliable, and maintainable

◉ Find logs wherever needed (Bug detection)

◉ Solves previous issues

3. TestNG

TestNG is an excellent plugin for Eclipse. Developers use it to perform unit, end-to-end, functional, and integration testing for Java projects. After performing tests, all errors found are reported in a new tab which helps you to fix issues efficiently. Also, it contains several templates to create easily. It comes with additional functionalities like data-driven testing, flexible test configuration, and execution models, and has default JDK functions for runtime and logging. If you’re new to Eclipse and don’t know how to install it, here you go – How to Install TestNG on Eclipse IDE?

Features of TestNG:

◉ Dependent groups, methods

◉ Multithreaded execution

◉ Uses more Java and Object-Oriented features

4. ADT (Android Development Tool)

Android Development Tool is an Eclipse plugin designed for Java developers with the intention to provide a robust and integrated environment to build android applications. It lets you perform tasks such as creating an application UI, adding packages on the basis of framework, and debugging applications. Java Programming Foundation – Self-Paced will help you ace the Java trends and will guide you with all the technical concepts. 

Features of ADT:

◉ Powerful and integrated plugin

◉ Custom XML editors

◉ Ability to customize extensively

◉ Supports multiple operating systems

5. Spring Tools

Spring Tool is the most popular Java plugin in Eclipse used to create Spring Boot projects. This plugin comes with tools used to run and monitor apps from inside IDE. You can also navigate through spring-specific code completion. It eases the development of applications by integrating Spring Boot with Initalzr. Having integration with Cloud Foundry, this plugin helps you to make it a perfect plugin for microservice development. The latest version used by Java developers is Spring Boot 4.

Features of Spring Tools:

◉ Provides you with run-time information

◉ Fast and productive

◉ Flexible plugin

◉ Secure and productive

6. EclEmma Java Code Coverage

Oracel Java, Oracle Java Tutorial and Materials, Core Java, Java Certification, Oracle Java Career, Java Skills, Java Jobs, Java News, Java Prep, Java Preparation
EclEmma, with its latest version 3.1.6 is available at the Eclipse marketplace is a free code coverage tool for Eclipse. It mainly focuses on supporting the individual developer in an interactive way. It was inspired by the great EMMA library which is developed by Vlad Roubtsov. It helps in faster development, also when the execution is done, it highlights the coverage results with different colors indicating different statuses. 

Features of EclEmma:

◉ Testing(JUnit, TestNG, SWTBOt)

◉ Analysis of code coverage

◉ Allows you to export/import files

◉ Speeds up your development

7. JRebel for Eclipse

JRebel is a tool used for productivity by developers to instantly reload code changes. It helps Java developers to create awesome applications very fast and gives them a high ROI productivity solution. It skips the rebuild, restart, and redeploy cycle common in Java development. It is easy to install and supports the majority of real-world enterprise Java stacks.

Features ofJRebel:

◉ Maintains state of the application

◉ Dedicated integration

◉ Visible real-time change

◉ Integrates with your stack seamlessly

Source: geeksforgeeks.org

Thursday, September 8, 2022

Inspect the contents of the Java Metaspace region

JVM Memory has following regions:

a. Young Generation

b. Old Generation

c. Metaspace

d. Others region

Oracle Java, Java Tutorial and Materials, Oracle Java Career, Oracle Java Skills, Oracle Java Jobs, Core Java, Oracle Java Prep, Oracle Java Preparation, Oracle Java News

To see what objects are stored in what region, you may refer to this video clip. Sometimes your application might run into ‘java.lang.OutOfMemoryError: Metaspace’ as discussed in this post. In such circumstances you might want to see what are the Contents loaded in the Metaspace region of the JVM. In nutshell, the Metaspace region in the JVM memory contains the class metadata definitions that are required to execute your application. If you want to understand what class metadata definitions means, you can refer to this documentation. It has intense details, you may not have to understand all the details of it. Basically if you can understand what are the classes that are loaded into memory, it will give a good idea what are the Contents that are present in the Metaspace region of the JVM memory. In this post let’s explore the options that are available to see the classes that are loaded into the Metaspace.

Below are the options to see the classes that are loaded in the Metaspace:

1. -verbose:class

2. -Xlog:class+load

3. jcmd GC.class_histogram

4. Programmatic approach

5. Heap Dump analysis

Let’s discuss each option in detail in this post.

1. -verbose:class


If you are running on Java version 8 or below then you can use this option. When you pass the ‘-verbose:class’ option to your application during startup, it will print all the classes that are loaded into memory. Loaded classes will be printed in the standard error stream (i.e. console, if you aren’t routing your error stream to a log file).

java {app_name} -verbose:class

Following is the sample output of the open source BuggyApp program when ‘-verbose:class’ argument is passed:

[Opened C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.Object from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.io.Serializable from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.Comparable from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.CharSequence from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.String from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.reflect.AnnotatedElement from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.reflect.GenericDeclaration from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.reflect.Type from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.Class from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.Cloneable from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.ClassLoader from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.System from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.Throwable from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.Error from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.ThreadDeath from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.Exception from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.RuntimeException from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.SecurityManager from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.security.ProtectionDomain from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.security.AccessControlContext from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.security.SecureClassLoader from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.ReflectiveOperationException from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.ClassNotFoundException from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.LinkageError from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.NoClassDefFoundError from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.ClassCastException from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.ArrayStoreException from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.VirtualMachineError from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.OutOfMemoryError from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]
[Loaded java.lang.StackOverflowError from C:\Program Files\Java\jre1.8.0_171\lib\rt.jar]

2. -Xlog:class+load


If you are running on Java version 9 or above then you can use this option. When you pass the ‘-Xlog:class+load’ option to your application during startup, it will print all the classes that are loaded into memory. Loaded classes will be printed in the file path you have configured.

java {app_name} -Xlog:class+load=info:/opt/log/loadedClasses.txt

Following is the sample output of a java program when ‘-Xlog:class+load’ argument is passed:

[0.004s][info][class,load] opened: /home/ec2-user/jdk-9.0.4/lib/modules
[0.006s][info][class,load] java.lang.Object source: jrt:/java.base
[0.007s][info][class,load] java.io.Serializable source: jrt:/java.base
[0.007s][info][class,load] java.lang.Comparable source: jrt:/java.base
[0.007s][info][class,load] java.lang.CharSequence source: jrt:/java.base
[0.007s][info][class,load] java.lang.String source: jrt:/java.base
[0.007s][info][class,load] java.lang.reflect.AnnotatedElement source: jrt:/java.base
[0.007s][info][class,load] java.lang.reflect.GenericDeclaration source: jrt:/java.base
[0.007s][info][class,load] java.lang.reflect.Type source: jrt:/java.base
[0.008s][info][class,load] java.lang.Class source: jrt:/java.base
[0.008s][info][class,load] java.lang.Cloneable source: jrt:/java.base
[0.008s][info][class,load] java.lang.ClassLoader source: jrt:/java.base
[0.008s][info][class,load] java.lang.System source: jrt:/java.base
[0.008s][info][class,load] java.lang.Throwable source: jrt:/java.base
[0.008s][info][class,load] java.lang.Error source: jrt:/java.base
[0.008s][info][class,load] java.lang.ThreadDeath source: jrt:/java.base
[0.008s][info][class,load] java.lang.Exception source: jrt:/java.base
[0.008s][info][class,load] java.lang.RuntimeException source: jrt:/java.base
[0.008s][info][class,load] java.lang.SecurityManager source: jrt:/java.base
[0.008s][info][class,load] java.security.ProtectionDomain source: jrt:/java.base
[0.009s][info][class,load] java.security.AccessControlContext source: jrt:/java.base
[0.009s][info][class,load] java.security.SecureClassLoader source: jrt:/java.base
[0.009s][info][class,load] java.lang.ReflectiveOperationException source: jrt:/java.base
[0.009s][info][class,load] java.lang.ClassNotFoundException source: jrt:/java.base
[0.009s][info][class,load] java.lang.LinkageError source: jrt:/java.base
[0.009s][info][class,load] java.lang.NoClassDefFoundError source: jrt:/java.base
[0.009s][info][class,load] java.lang.ClassCastException source: jrt:/java.base
[0.009s][info][class,load] java.lang.ArrayStoreException source: jrt:/java.base
[0.009s][info][class,load] java.lang.VirtualMachineError source: jrt:/java.base
[0.009s][info][class,load] java.lang.OutOfMemoryError source: jrt:/java.base
[0.009s][info][class,load] java.lang.StackOverflowError source: jrt:/java.base
[0.009s][info][class,load] java.lang.IllegalMonitorStateException source: jrt:/java.base
[0.009s][info][class,load] java.lang.ref.Reference source: jrt:/java.base
[0.009s][info][class,load] java.lang.ref.SoftReference source: jrt:/java.base
[0.009s][info][class,load] java.lang.ref.WeakReference source: jrt:/java.base
[0.009s][info][class,load] java.lang.ref.FinalReference source: jrt:/java.base
[0.009s][info][class,load] java.lang.ref.PhantomReference source: jrt:/java.base
[0.009s][info][class,load] java.lang.ref.Finalizer source: jrt:/java.base
[0.009s][info][class,load] java.lang.Runnable source: jrt:/java.base
[0.009s][info][class,load] java.lang.Thread source: jrt:/java.base
[0.009s][info][class,load] java.lang.Thread$UncaughtExceptionHandler source: jrt:/java.base
[0.009s][info][class,load] java.lang.ThreadGroup source: jrt:/java.base
[0.010s][info][class,load] java.util.Map source: jrt:/java.base
[0.010s][info][class,load] java.util.Dictionary source: jrt:/java.base
[0.010s][info][class,load] java.util.Hashtable source: jrt:/java.base
[0.010s][info][class,load] java.util.Properties source: jrt:/java.base
[0.010s][info][class,load] java.lang.Module source: jrt:/java.base
[0.010s][info][class,load] java.lang.reflect.AccessibleObject source: jrt:/java.base

3. jcmd GC.class_histogram


JDK contains a tool called ‘jcmd’. You can invoke this tool when JVM is running to inspect the Contents of the Metaspace region. When you invoke this tool with ‘GC.class_histogram’ argument, it will print the list of classes that are loaded into the memory.  You can invoke this tool in two modes:

a. Print loaded classes on the console

jcmd {pid} GC.class_histogram

When you invoke the ‘jcmd’ as shown above it will print all the loaded classes in the console. Here {pid} is the process id of your java application. 

b. Print loaded classes on a File

jcmd {pid} GC.class_histogram filename={file-path}

When you invoke the ‘jcmd’ as shown above, it will print all the loaded classes in the file path specified in the ‘filename’ argument. Here {pid} is the process id of your java application.

Here is a blog post which helps you to identify the process id quickly.

Following is the sample output of the open source BuggyApp program when ‘jcmd GC.class_histogram’ argument is passed:

jcmd 19684 GC.class_histogram
19684:
 
 num     #instances         #bytes  class name
----------------------------------------------
   1:        143036       75523008  [Ljavassist.bytecode.ConstInfo;
   2:        718060       70032224  [C
   3:       1573553       50353696  java.util.HashMap$Node
   4:        430124       24732832  [Ljava.lang.Object;
   5:       1001290       24030960  javassist.bytecode.Utf8Info
   6:        858268       20598432  java.util.ArrayList
   7:        718037       17232888  java.lang.String
   8:        144011       14987488  java.lang.Class
   9:        143081       11447152  [Ljava.util.HashMap$Node;
  10:        143036        9154304  javassist.bytecode.ClassFile
  11:        143035        9154240  javassist.CtNewClass
  12:        286124        6892400  [B
  13:        143085        6868080  java.util.HashMap
  14:        286078        6865872  javassist.bytecode.ClassInfo
  15:        143036        6865728  [[Ljavassist.bytecode.ConstInfo;
  16:        143049        5721960  javassist.bytecode.MethodInfo
  17:        143042        5721680  javassist.bytecode.CodeAttribute
  18:        143323        4586336  java.util.Hashtable$Entry
  19:        143038        4577216  java.lang.ref.WeakReference
  20:        143036        4577152  javassist.bytecode.ConstPool
  21:        143045        3433080  javassist.bytecode.MethodrefInfo
  22:        143045        3433080  javassist.bytecode.NameAndTypeInfo
  23:        143042        3433008  javassist.bytecode.ExceptionTable
  24:        143036        3432864  javassist.bytecode.LongVector
  25:        143036        3432864  javassist.bytecode.SourceFileAttribute
  26:        143622        2323336  [I
  27:            10         788688  [Ljava.util.Hashtable$Entry;
  28:           642          20544  java.util.concurrent.ConcurrentHashMap$Node
  29:           244          13664  java.lang.invoke.MemberName
  30:           341          10912  sun.misc.FDBigInteger
  31:           212           8480  java.lang.ref.SoftReference
  32:           140           8400  [Ljava.lang.ref.SoftReference;
  33:           234           7488  java.lang.invoke.LambdaForm$Name
  34:           176           7040  java.lang.invoke.MethodType
  35:           256           6144  java.lang.Long
  36:            16           6016  java.lang.Thread
  37:           173           5880  [Ljava.lang.Class;
  38:           366           5856  java.lang.Object
  39:           177           5664  java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry
  40:            10           5280  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  41:           256           4096  java.lang.Byte
  42:           256           4096  java.lang.Integer
  43:           256           4096  java.lang.Short
  44:            73           4088  java.lang.invoke.MethodTypeForm
  45:            82           3808  [Ljava.lang.invoke.LambdaForm$Name;
  46:            77           3696  java.lang.invoke.LambdaForm

4. Programmatic approach


You can also use a programmatic approach to print the classes that are loaded into the memory. Open source Guava library provides APIs to print the loaded classes. Below is the code sample that leverage Guava library to print the loaded classes in the memory:

ClassPath classPath = ClassPath.from(BuggyAppLoader.class.getClassLoader());
Set<ClassInfo> classes = classPath.getAllClasses();
for(ClassInfo classInfo : classes) {
    logger.info(classInfo.getName());
}

org.apache.catalina.core.AsyncContextImpl
org.apache.catalina.core.AsyncListenerWrapper
org.apache.catalina.core.Constants
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor
org.apache.catalina.core.ContainerBase$PrivilegedAddChild
org.apache.catalina.core.ContainerBase$StartChild
org.apache.catalina.core.ContainerBase$StartStopThreadFactory
org.apache.catalina.core.ContainerBase$StopChild
org.apache.catalina.core.ContainerBase
org.apache.catalina.core.DefaultInstanceManager$1
org.apache.catalina.core.DefaultInstanceManager$2
org.apache.catalina.core.DefaultInstanceManager$3
org.apache.catalina.core.DefaultInstanceManager$AnnotationCacheEntry
org.apache.catalina.core.DefaultInstanceManager$AnnotationCacheEntryType
org.apache.catalina.core.DefaultInstanceManager
org.apache.catalina.core.JreMemoryLeakPreventionListener
org.apache.catalina.core.NamingContextListener
org.apache.catalina.core.StandardContext$1
org.apache.catalina.core.StandardContext$ContextFilterMaps
org.apache.catalina.core.StandardContext$NoPluggabilityServletContext
org.apache.catalina.core.StandardContext
org.apache.catalina.core.StandardContextValve
org.apache.catalina.core.StandardEngine$AccessLogListener
org.apache.catalina.core.StandardEngine$NoopAccessLog
org.apache.catalina.core.StandardEngine
org.apache.catalina.core.StandardEngineValve
org.apache.catalina.core.StandardHost$1
org.apache.catalina.core.StandardHost$MemoryLeakTrackingListener
org.apache.catalina.core.StandardHost
org.apache.catalina.core.StandardHostValve
org.apache.catalina.core.StandardPipeline
org.apache.catalina.core.StandardServer
org.apache.catalina.core.StandardService
org.apache.catalina.core.StandardThreadExecutor
org.apache.catalina.core.StandardWrapper
org.apache.catalina.core.StandardWrapperFacade
org.apache.catalina.core.StandardWrapperValve
org.apache.catalina.core.ThreadLocalLeakPreventionListener

5. Heap Dump analysis


Another option to see the classes that are loaded into memory is to inspect Heap Dump. Heap dump reports all the data, objects, classes that are loaded into memory. You can use one of the approaches given here to capture the heap dump. Once a heap dump is captured, you can use the heap dump analysis tools such as Eclipse MAT, HeapHero,… to analyze the heap dump.

Below is the excerpt from the report generated by the HeapHero tool that shows the classes that are loaded into the memory.

Oracle Java, Java Tutorial and Materials, Oracle Java Career, Oracle Java Skills, Oracle Java Jobs, Core Java, Oracle Java Prep, Oracle Java Preparation, Oracle Java News

Note: All the approaches mentioned above will not add noticeable overhead to your application, however the heap dump approach is an intrusive option and it will add considerable overhead to your application. When heap dump is captured your application will be paused until capturing is complete.

Source: javacodegeeks.com