HOAB

History of a bug

Swing application freeze

Rédigé par gorki Aucun commentaire

Problème :

J'ai une application en client lourd java qui fonctionnait bien. Depuis quelques jours, elle freeze quand j'ouvre une série de popup ce qu'elle ne faisait pas avant (ou que je n'avais pas remarqué)

Solution :

J'ai désactivé les agents que j'avais en même temps, supprimer les options inutiles de la JVM, toujours rien.

La stacktrace me dit ceci :

"pool-19-thread-1" #175 prio=5 os_prio=0 tid=0x00007fe2b4055000 nid=0x5ee3 waiting for monitor entry [0x00007fe3d2efd000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at java.awt.KeyboardFocusManager.clearMostRecentFocusOwner(KeyboardFocusManager.java:1882)
        - waiting to lock <0x00000000e081d6e0> (a java.awt.Component$AWTTreeLock)
        at java.awt.Component.disable(Component.java:1526)
        at javax.swing.JComponent.disable(JComponent.java:3639)
        at java.awt.Component.enable(Component.java:1515)
        at java.awt.Component.setEnabled(Component.java:1478)
        at javax.swing.JComponent.setEnabled(JComponent.java:2680)
        at javax.swing.JComboBox.setEnabled(JComboBox.java:1391)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

"SwingWorker-pool-4-thread-7" #171 daemon prio=5 os_prio=0 tid=0x00007fe33c6ff000 nid=0x5edf waiting on condition [0x00007fe3bbefb000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000fb81e808> (a java.util.concurrent.FutureTask)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
        at java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at org.GNOME.Accessibility.AtkUtil.invokeInSwing(AtkUtil.java:68)
        at org.GNOME.Accessibility.AtkObject.hashCode(AtkObject.java:234)
        at org.GNOME.Accessibility.AtkWrapper.emitSignal(Native Method)
        at org.GNOME.Accessibility.AtkWrapper$5.propertyChange(AtkWrapper.java:545)
        at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
        at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:327)
        at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:263)

Au final, ce lienj'ai trouvé ce lien et j'ai ajouté l'option Java sur la ligne de commande. Tout est OK.

-Djavax.accessibility.assistive_technologies=

Pour plus d'informations :

https://docs.oracle.com/javase/8/docs/technotes/guides/access/new-features.html

Logitech Media Server and Synology DS218play

Rédigé par gorki Aucun commentaire

Problem :

Logitech media server is not supported anymore by Synology (bouuuuh.)

Spotted by number of threads :

  • https://community.synology.com/enu/forum/1/post/141628
  • https://www.avforums.com/threads/synology-and-lms.2332981/
  • https://community.jeedom.com/t/synology-maj-package-perl-lms-squeezebox-hs/57576
  • https://www.homecinema-fr.com/forum/source-dematerialisee-haute-fidelite-et-dac/logitech-squeezebox-t29927392-7185.html

I have a DS218play, ARMv8 based

Solution :

Instead of switching back to the old package, or create my new one, I decided to install docker.

I followed this thread : https://stackoverflow.com/questions/52520008/can-i-install-docker-on-arm8-based-synology-nas

Quite easy.

I follow also the script here : https://raw.githubusercontent.com/wdmomoxx/catdriver/master/install-docker.sh but I download docker from original site instead.

I use this image : https://registry.hub.docker.com/r/lmscommunity/logitechmediaserver/#!

And run this command, not perfect (log, daemon, docker image should be started... will update this later).

#!/bin/bash

docker run --network=host -it \
      -v "/volume1/partage/docker/lms/config":"/config":rw \
	  -v "/volume1/music":"/music":ro \
	  -v "/volume1/partage/docker/lms/playlist":"/playlist":rw \
	  -v "/etc/localtime":"/etc/localtime":ro \
	  -v "/etc/TZ":"/etc/timezone":ro \
	  -v "/dev":"/dev" \
       lmscommunity/logitechmediaserver &> /volume1/partage/docker/lms-docker.log

Added :  --network=host  (and remove mapping port) and -v "/dev":"/dev"

Raspberry as network monitor

Rédigé par gorki Aucun commentaire

Problem :

I built a network monitoring solution following this guides :

Truly, a great job.

But I has build the solution at home for another network, I would like that my raspberry start and monitor at boot. And I missed in the comments or text a few thing.

Solution :

I created services as described in the comment for prometheus, add another for the tcpdump. Don't forget prometheus working directory in this configuration (no specific user for prometheus).
 

[Unit]
Description=Prometheus
After=tcpdump.service

[Service]
User=pi
Group=pi
Type=simple
WorkingDirectory=/home/pi/prometheus/prometheus-2.23.0.linux-armv7
ExecStart=/home/pi/prometheus/prometheus-2.23.0.linux-armv7/prometheus \
    --config.file /home/pi/prometheus/prometheus.yml

[Install]
WantedBy=multi-user.target
/etc/systemd/system/tcpdump.service

[Unit]
Description=TCPDump service for traffic monitoring
After=network-online.target
[Service]
Type=idle
ExecStart=python3 /home/pi/network-traffic-metrics/network-traffic-metrics.py "(src net 192.168.10.0/24 and not dst net 192.168.10.0/24) or (dst net 192.168.10.0/24 and not src net 192.168.10.0/24)"
[Install]
WantedBy=default.target

But I had some network issues :

First, disable dhcpcd and install isc-dhcp-server

In my case, I keep dhcpcd as it mount the network interfaces eth0 & eth1. I also put a no gateway on eth0 (my lan part)

My dhcpcd.conf configuration for interfaces :


interface eth1
static ip_address=192.168.1.10
static routers=192.168.1.1
static domain_name_servers=1.1.1.1
static domain_search=1.1.1.1

interface eth0
static ip_address=192.168.10.1
static routers=192.168.10.1
static domain_name_servers=1.1.1.1
static domain_search=1.1.1.1
nogateway

But with this configuration, at boot :

  • isc-dhcp-server and tcpdump

were not started because eth0 was not up or plugged. In my case, I could plug eth0 later.

So I took a while, but I found the network hook that works (forget all /etc/network thing, dhcpcd do not use it).

Create a file (not a directory...) called /etc/dhcpcd.exit-hook with

#!/bin/bash

if [ "$interface" = "eth0" & "$reason" = "STATIC" & "$if_up" = "true" ]
then
	systemctl start tcpdump
	systemctl start isc-dhcp-server.service
fi 

And all is starting when eth0 is going up.

IE11 et cache-control rules

Rédigé par gorki Aucun commentaire

Problem :

I had a problem, nearly simple : on an angular 11 application, font was not displayed on IE11 on customer site.

After a few tests :

  • I reproduce it on my demo site
  • I do not reproduce in dev mode

Solution :

Well, I search for a while, and here is a summary.

  1. IE11 has a problem if header "Cache-Control: nostore" is set for fonts... Not easy to find but there is some reference here
  2. On my dev, it's working, after a check, I'm not setting Cache-Control: nostore
  3. On my demo site, I have this header, but I have a Nginx as a reverse proxy. Ok, that's why
  4. On customer site, I do not have control on network elements. One must add it also

I made the assumption that if I set a Cache directive, intermediate server won't modify it.

It works on my demo site. I'll check next on my customer site.

To add cache control on springboot, thanks Baeldung !

        registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/static/hpa-portal/assets/")
                .setCacheControl(CacheControl.maxAge(1, TimeUnit.DAYS));

 

 

Back to basics : hashcode and hashmap

Rédigé par gorki Aucun commentaire

Problem :

I'm building a Java agent to monitor objects. I track some objects and get metrics ont it. But to have less impact on memory, if objects are removed, I don't want to keep a reference to them. It could prevent the garbage collector to remove them.

Objects can be scanned multiple time for some reasons, so to keep a unique reference, I built an hashmap to track only one reference of these objects.

A hashmap with weak reference.

As stated by this article, weak reference can not be compared regarding their reference but only between WeakReference objects themselves. So I used the proposal of this article and create a WeakEqualReference object.

Adding is working well.

But after a while, I can not remove an object : I go through the map, I tried to remove an object given by the entrySet iterator : impossible.

Solution :

Well, I search for a while, and here is a summary.

In the article, hashcode used for WeakEqualReference is :

	@Override
	public int hashCode() {
		T value = this.get();
		return value != null ? value.hashCode() : super.hashCode();
	}

In fact, it gives :

  1. on the first call : the hashcode of the value
  2. on the second call, after value has been removed : the hashcode of the WeakEqualsReference

But when object is stored in the hashmap, this is the first hashcode which is used. And the hashmap never find the new hashcode after the value becomes null. Containskey, remove, all is wrong.

Hashcode must be consistent for the duration of the WeakEqualsReference.

So, my solution is to compute the hascode on the first call, when the object is stored in the hashmap, return it each times after that. WeakEqualsReference can now be removed safely.

import java.lang.ref.WeakReference;

public class WeakEqualReference<T> extends WeakReference<T> {

	private int hashCode = 0;

	public WeakEqualReference(T r) {
		super(r);
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean equals(Object other) {

		boolean returnValue = super.equals(other);

		// If we're not equal, then check equality using referenced objects
		if (!returnValue && (other instanceof WeakEqualReference<?>)) {
			T value = this.get();
			if (null != value) {
				T otherValue = ((WeakEqualReference<T>) other).get();

				// The delegate equals should handle otherValue == null
				returnValue = value.equals(otherValue);
			}
		}

		return returnValue;
	}

	@Override
	public int hashCode() {
		if (hashCode == 0) {
			T value = this.get();
			hashCode = value != null ? value.hashCode() : super.hashCode();
		}
		return hashCode;
	}
}

And for the story :

- one of my values referenced was a bean with a String and another instance of WeakEqualsReference. I still had issue, but due to the String ! This string value was updated so hashcode before and after was different. Same cause, same effects.

Here the example was complicated by the WeakReference usage, but with a simple HashSet :


import java.util.HashSet;
import java.util.Objects;

public class HashCodeTest {

    public static class HashTestValue {
        public String value;

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            HashTestValue that = (HashTestValue) o;
            return Objects.equals(value, that.value);
        }

        @Override
        public int hashCode() {
            return Objects.hash(value);
        }
    }


    public static void main(String... args) {

        HashSet<HashTestValue> set = new HashSet();

        HashTestValue mapTestValue = new HashTestValue();
        mapTestValue.value = "1234";
        set.add(mapTestValue);

        System.out.println("set.contains(mapTestValue) = " + set.contains(mapTestValue));

        mapTestValue.value = "5678";

        System.out.println("set.contains(mapTestValue) = " + set.contains(mapTestValue));

    }
}

Conclusion : overriding equals and hascode is OK, but be careful of the consistency if you need to test the object after the insert !

 

Fil RSS des articles