Java : le projet Valhalla validé par Oracle
Pour préparer le terrain aux futures évolutions de la plateforme

Le , par Hinault Romaric

0PARTAGES

1  0 
Le projet Valhalla pour la plateforme Java prend forme. Annoncé il y a quelques mois par Brian Goetz, responsable du projet, celui-ci a été validé par Oracle.

Le projet Valhalla est une sorte d’incubateur pour le développement des futures fonctionnalités de la plateforme Java. Celui-ci va tenter d’améliorer le langage Java en l’affectant à différents niveaux, comme le typage, le langage, la machine virtuelle ou les bibliothèques. Le projet a pour vocation de définir une sémantique claire au niveau de la machine virtuelle pour permettre un support égal pour le langage Java et les autres langages recourant à la JVM.

La révision majeure dans la description actuelle du projet concerne les génériques. Les versions actuelles de Java ne permettent pas que les types génériques contiennent les types primitifs, et le compilateur Java supprime les détails du type contenu lors de la compilation. Cette approche de typage générique (effacement de type) représente l’un des aspects assez critiqués du système de types de Java.

Le projet Valhalla explorera une nouvelle approche pour la gestion des types génériques, et espère produire une nouvelle forme de typage générique, qui permettra aux développeurs d’appliquer des génériques aux types primitifs. Ainsi, dans les futures versions de Java, des déclarations telles que List<int> pourront être valides en Java.

D’autres modifications importantes sont également au menu comme les types valeurs, qui permettront une optimisation de la représentation mémoire des types tout en maintenant les mêmes performances. Les types valeurs auront pour objectif de combiner certaines propriétés des types primitifs et des types objets, pour donner naissance à un nouveau type, qui sera manipulé par le développeur comme un type primitif.

Les développeurs intéressés par le projet peuvent rejoindre sa liste de diffusion sur le site d’OpenJDK. Brian Goetz a souligné dans l’annonce que le projet est encore à un stade embryonnaire, donc la communauté ne devrait pas s’attendre à trouver une technologie développée au sein de Valhalla dans JDK 9, dont la version finale est prévue pour 2016.

Annonce du projet projet Valhalla

Description du projet Valhalla

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de super_navide
Nouveau Candidat au Club https://www.developpez.com
Le 29/07/2014 à 16:45
Avec cette nouveauté :
D’autres modifications importantes sont également au menu comme les types valeurs, qui permettront une optimisation de la représentation mémoire des types tout en maintenant les mêmes performances. Les types valeurs auront pour objectif de combiner certaines propriétés des types primitifs et des types objets, pour donner naissance à un nouveau type, qui sera manipulé par le développeur comme un type primitif.

On peut dire adieu au C++ le point faible de java était ne pas pouvoire définir des types primtif comme les points et autre structure pour éviter d’allouer de la mémoire.
reste plus qu'a pouvoir surcharger les opérateurs comme + - / etc..
et on pourra écrire de jolie addition de vecteur V+U aussi rapide qu'en C++.
Avatar de Thyxx
Membre régulier https://www.developpez.com
Le 29/07/2014 à 17:03
Citation Envoyé par super_navide Voir le message
On peut dire adieu au C++

Mais tout à fait...
Avatar de tomlev
Rédacteur/Modérateur https://www.developpez.com
Le 29/07/2014 à 17:07
Citation Envoyé par super_navide Voir le message
reste plus qu'a pouvoir surcharger les opérateurs comme + - / etc..
Bah dans ce cas tu peux faire du C#, qui fait tout ce que fait Java, a des types valeur et permet la surcharge d'opérateurs

(bah oui, je prêche pour ma paroisse, hein )
Avatar de benjani13
Membre extrêmement actif https://www.developpez.com
Le 30/07/2014 à 1:17
Citation Envoyé par super_navide Voir le message
On peut dire adieu au C++ le point faible de java était ne pas pouvoire définir des types primtif comme les points et autre structure pour éviter d’allouer de la mémoire.
reste plus qu'a pouvoir surcharger les opérateurs comme + - / etc..
et on pourra écrire de jolie addition de vecteur V+U aussi rapide qu'en C++.
Si les features du C++ t'interesse, pourquoi ne fais tu pas du C++ au lieu d'attendre que Java implémente ces features? Vous trouvez pas que c'est paradoxal? (le premier qui me répond "c'est pas faux" ).

Citation Envoyé par tomlev Voir le message
Bah dans ce cas tu peux faire du C#, qui fait tout ce que fait Java, a des types valeur et permet la surcharge d'opérateurs

(bah oui, je prêche pour ma paroisse, hein )
+1

C#
Avatar de professeur shadoko
Membre expérimenté https://www.developpez.com
Le 30/07/2014 à 10:27
Citation Envoyé par super_navide Voir le message

reste plus qu'a pouvoir surcharger les opérateurs comme + - / etc..
la surcharge d'opérateur a été refusée par l'équipe initiale de java pour éviter une confusion à la lecture du code.
Un des points fondamentaux de la philosophie initiale était: ce qui est compilé est ce qui est explicitement écrit ... malheureusement des évolutions ultérieures ont un peu contourné cette règle
mais la surcharge d'opérateur rend la lecture des codes C++ incroyablement difficile , et les programmeurs en abusent en violant allégrement la sémantique de l'opérateur.... vade retro satanas ...
(quoiqu'en Scala il y a un point de vue plus amusant sur la question, voir aussi en Groovy ... mais en Java j'espère que cette demande n'aboutira jamais )
edit: C# c'est la philosophie Microsoft: vous en voulez? alors en voilà! Peu importe si ça abouti à des formalismes peu en accord avec les règles du génie Logiciel (ou à des incohérences: je pense ici à la vision Microsoft de SQL qui donne un sens à des expressions illégales parce que les utilisateurs font souvent l'erreur ... alors ils donnent un sens à ce qui n'en a pas!)
Avatar de super_navide
Nouveau Candidat au Club https://www.developpez.com
Le 30/07/2014 à 16:38
et les programmeurs en abusent en violant allégrement la sémantique de l'opérateur.... vade retro satanas ...
Quel sémanatique de l'opérateur le symbol multiplication en math est utilisé pour les matrices et pour les nombre et ca sémantique n'est pas la même
sur les matrice ils perd la commutativité et la transitivité.
Donc le viol de sémantique n'existe pas.
encore une regle stupide que certain informaticien ce donne................
Avatar de Gugelhupf
Modérateur https://www.developpez.com
Le 30/07/2014 à 16:59
Bonjour,

J'ai lu la JEP 193 concernant l'évolution de "volatile" mais je n'ai pas tout à fait saisi l'objectif de ".volatile".

Est-ce qu'en faisant :
Code : Sélectionner tout
1
2
3
4
5
6
7
// Exemple de la JEP
class Usage {
    volatile int count;
    int incrementCount() {
        return count.volatile.incrementAndGet();
    }
}
L'idée c'est de faire quelque chose comme :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
class Usage {
    volatile int count;
    int incrementCount() {
        synchronized {
            return count.incrementAndGet();
        }

        return 0;
    }
}
?

Merci
Avatar de adiGuba
Expert éminent sénior https://www.developpez.com
Le 30/07/2014 à 17:55
Citation Envoyé par Gugelhupf Voir le message
J'ai lu la JEP 193 concernant l'évolution de "volatile" mais je n'ai pas tout à fait saisi l'objectif de ".volatile".
Non.

L'idée c'est d'avoir le même mécanisme que les classes AtomicInteger, etc. qui n'ont pas recours à la synchronisation.

Il faut savoir que les seules opérations atomiques c'est l'affectation d'une valeur :
Code : Sélectionner tout
1
2
3
count = 15;
// ou 
int temp = count;


Mais dès qu'il y a un calcul au milieu on n'est plus atomique, par exemple une incrémentation :
Code : Sélectionner tout
count += 1; // ou count++
En effet cela se décompose en fait en plusieurs instructions, que l'on pourrait représenter comme cela (en vrai c'est du bytecode, mais pour l'exemple je laisse en java) :
Code : Sélectionner tout
1
2
3
int next = count;
next++;
count = next;
Le problème c'est que si un autre thread modifie "count" entre ces deux opérations on se retrouve avec une valeur incorrect.

Par exemple si tu as deux threads qui incrément de 1 en même temps tu peux avoir cela :
Code : Sélectionner tout
1
2
3
4
int count = 0; // etat initial

count += 1; // thread 1
count += 1; // thread 2
On pourrait penser que le résultat sera forcément "2", mais ce n'est pas garantie.
En effet en décomposant on a en fait ceci :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
int count = 0; // etat initial

int next1 = count; // thread 1 (count vaut 0)
next1++; // thread 1
count = next1; // thread 1

int next2 = count; // thread 2  (count vaut 1)
next2++;  // thread 2
count = next2; // thread 2
Sauf que l'ordonnanceur peut nous jouer des tours, et on obtient alors une exécution qui ressemble à quelque chose comme cela :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
int count = 0; // etat initial

int next1 = count; // thread 1 (count vaut 0)
int next2 = count; // thread 2 (count vaut 0)

next1++; // thread 1
next2++; // thread 2

count = next1; // thread 1
count = next2; // thread 2
Du coup next1 et next2 valent tous les deux "1", et count prend finalement la valeur "1" alors qu'on l'a incrémenté deux fois !

En clair entre le moment ou on fait notre calcul et le moment ou on affecte le résultat dans la variable, la variable a été modifié par un autre thread
Du coup on devrait avoir un résultat différent, et notre calcul fait "disparaitre" la modif précédente...

En fait les classes AtomicXXX se base sur le compareAndSet, qui permet d'affecter une variable seulement si sa valeur correspond bien à celle indiqué.
Du coup l'incrémentation correspond plutôt à ceci :
Code : Sélectionner tout
1
2
3
int old = count;
int next = old + 1;
count.volatile.compareAndSet(old, next); // ne marche QUE si la valeur de count == old
L'idée c'est donc de faire cela dans une boucle, jusqu'à ce que compareAndSet() fonctionne.
Ainsi si "count" a été modifié par un autre thread entre temps, on reprend le calcul avec la valeur modifié et on réessaye.

C'est grosso-modo ce que font les méthodes d'AtomicInteger.
Cela peut paraitre curieux, mais c'est plus efficace que la synchronisation (cela n'a quasiment aucun "coût" lorsque la variable n'est pas modifié entre temps).
C'est même plus sûr car il n'y a pas forcément besoin d'utiliser synchronized sur toutes les utilisations de la variable...

L'objectif de la JEP c'est de permettre cela directement sur un attribut primitif, sans pour autant passer par les classes AtomicXXX...

a++
Avatar de Gugelhupf
Modérateur https://www.developpez.com
Le 31/07/2014 à 0:08
Bonsoir,

Merci pour les explications adiGuba , je connais déjà plus ou moins le comportement des variables dans un environnement multi-thread. Ce que je ne connais pas par contre, c'est le mécanisme interne des AtomicXXX et sa différence par rapport synchronized.

Donc si je comprends bien : ".volatile" va faire comme AtomicXXX (qui n'utilise pas synchronized), mais en simplifiant la syntaxe lourde de AtomicXXX.

J'ai donc décidé d'aller regarder l'implémentation de la méthode compareAndSet() de AtomicInteger pour essayer de comprendre le mécanisme de la "boucle" dont tu fais référence. La méthode compareAndSet() fait intervenir la méthode native compareAndSwapInt() du type sun.misc.Unsafe, on tombe sur du code ASM :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Version Linux :
#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: "
// ... 
inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  int mp = os::is_MP();
  __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"
                    : "=a" (exchange_value)
                    : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
                    : "cc", "memory");
  return exchange_value;
}


// Version Windows :
#define LOCK_IF_MP(mp) __asm cmp mp, 0  \
                       __asm je L0      \
                       __asm _emit 0xF0 \
                       __asm L0:
// ...
inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
  // alternative for InterlockedCompareExchange
  int mp = os::is_MP();
  __asm {
    mov edx, dest
    mov ecx, exchange_value
    mov eax, compare_value
    LOCK_IF_MP(mp)
    cmpxchg dword ptr [edx], ecx
  }
}
L'assembleur n'est pas ma tasse de thé, je vois bien que la clé se situe au niveau de l'instruction cmpxchg et qu'il y a un saut dans les 2 cas, mais le saut se situe vers le bas, donc je ne vois pas de "boucle" mais plutôt un lock avec une sorte de signal...
Avatar de M_Makia
Membre averti https://www.developpez.com
Le 31/07/2014 à 7:31
C'est une très bonne nouvelle.
La langage Java accuse d'un retard non négligeable par rapport à d'autres langages (Scala, Python, C# ...).
Il est temps de dépoussiérer un peu tout ça ^^
Contacter le responsable de la rubrique Accueil

Partenaire : Hébergement Web