Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Des ingénieurs d'Oracle proposent d'étendre Java avec des types intermédiaires
à mi-chemin entre les classes et les types primitifs

Le , par Arsene Newman

0PARTAGES

2  0 
« Codé comme une classe, fonctionne comme un entier », voilà la devise de trois ingénieurs d’Oracle pour améliorer le langage Java. En effet, Brian Goetz, John Rose et Guy Steele viennent de publier le premier draft de leur proposition qui s’intitule State of the Values .

Leur proposition qui est encore à ses balbutiements vise à étendre le langage Java et la JVM avec une nouvelle catégorie de type appelée Value types qui devrait s’inscrire à mi-chemin entre les types primitifs et les classes. Le but de la manœuvre est de créer de nouveaux types qui seraient codés comme une classe et qui bénéficieraient des mécanismes qui lui sont spécifiques comme l’encapsulation, tout en offrant de meilleures performances en termes de mémoire utilisée et de CPU que les classes.

Les trois instigateurs de cette proposition appuient leur idée avec un constat simple : les objets font appel à la notion d’identité de l’objet qui est là en premier lieu pour permettre la mutabilité et le polymorphisme, ce qui a un cout important sur les performances du langage et de la JVM.

Toutefois, dans certains cas, l’utilisateur code une classe qui s’affranchit de la notion d’identité de l’objet. Par exemple, l’utilisateur définit en premier lieu une classe Point qui représente un point sur un plan 2D, en sachant que cette dernière ne sera pas « castée » en un autre objet. Il devient intéressant de l’avoir comme un Value Types.

Enfin, il est important de noter que cette proposition peut ouvrir la voie à pas mal d’améliorations pour le langage Java comme le soulignent les trois ingénieurs. Cela permettrait notamment de définir certains nombres mathématiques qui ne sont pas encore présents comme les nombres complexes ou permettre le support de certains types natifs et spécifiques aux processeurs modernes, sans oublier un tas d’autres améliorations telles que notées dans leur proposition.

Source : State of the Values

Et vous ?

Qu’en pensez-vous ?

Pensez-vous que cette proposition peut être bénéfique au langage ? Pourquoi ?

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

Avatar de adiGuba
Expert éminent sénior https://www.developpez.com
Le 13/05/2014 à 10:23
@la.lune : l'idée du type Value ce n'est pas de faire des "gros" type de données, mais de modéliser des types de bases "simples", qui à les encapsuler dans des objets plus complexes (ou des tableaux).

A “soft” restriction on values is that they are “not too large”. Values with tens of components, though legal, are not the design center of this proposal. Since values are passed, well, by value, the overhead of copying many components is increasingly likely to overwhelm any savings obtained by removing the overhead of a pointer and an object header, as the number of components grows. Large groups of component values should usually be modeled as plain classes, since they can be passed around under single pointers.

L'intérêt étant de limiter l'utilisation mémoire et le travail du GC.

Exemple, si tu as un tableau de 100 000 Point :
Code : Sélectionner tout
Point[] points = new Point[100_000];
Si Point est un Object :
  • Un objet Point occupera environ entre 16 et 22 octets en mémoire (4 pour chacun des deux int, puis entre 8 et 16 pour l'header de l'objet). Bien sûr cela peut varier selon la JVM...
  • Le tableau "points" va comporter 100 000 références de 4 octets soit une utilisation mémoire de 400 000 octets (voir même 800 000 octets selon la JVM en 64bits où les références peuvent occuper 8 octets).
  • Lorsque tu affectes un Point dans le tableau (points[0] = new Point(1,2);), la mémoire occupé par le tableau ne va pas changer (tu changes juste la valeur de la référence).
    Par contre tu va créer un objet Point en mémoire dans le heap, en restant sur un objet de 16 octets cela peut occuper jusqu'à 1 600 000 octets si ton tableau comporte des références distinctes.
  • Et à chaque nouvelle affectation sur le tableau, tu crées un nouvel objet et tu en libère un nouveau, ce qui donnera du travail au GC.


D'une part la consommation mémoire est importante (400 000 + 1 600 000 soit 2 000 000 octets si le tableau est remplit), mais l'utilisation mémoire peut varier selon les manipulations effectués sur le tableau, car cela implique la création d'objet dans le heap (et donc de donner du travail au GC).

Si Point est un type Value :
  • Une value Point occupera juste 8 octets (4 pour chaque int). Il n'y a pas besoin de stocker des informations sur l'header...
  • Le tableau de "points" va directement comporter 100 000 valeur "Point" de 8 octets, soit une utilisation de 800 000 octets (quel que soit la JVM).
  • Lorsque tu affectes un type value Point dans le tableau (points[0] = __MakeValue Point(1,2);), tu écraseras directement la valeur dans le tableau.
    Aucun nouvel objet ne sera crée en mémoire, donc le GC n'aura aucun travail à faire (si ce n'est à gérer la référence du tableau).
  • A chaque nouvelle affectation du tableau, la valeur est modifier directement dans le tableau (pas d'allocation de mémoire).


L'utilisation mémoire est fixe quel que soit le contenu du tableau, et limité au strict minimum (800 000 octets), là où le tableau d'objet peut utiliser 2 fois plus de mémoire.
La manipulation du tableau de type Value n'implique aucune création d'objet dans le heap, et limite donc le travail du GC.

a++
5  0 
Avatar de adiGuba
Expert éminent sénior https://www.developpez.com
Le 11/05/2014 à 8:10
Salut,

Citation Envoyé par thelvin Voir le message
Chose impossible avec les types de base et valueTypes, d'où le problème original que j'évoquais, comment on leur donne une valeur par défaut puisque c'est pas null.
Ce problème est évoqué dans la proposition, à la fin de la section "General approach: usage" :
A fourth aspect of primitives is that, although they do not have values that correspond to the null reference, they do have default values, generally some sort of zero. This default value shows up in the initial contents of uninitialized fields and array elements. It is therefore necessary to specify a default value for each value type. The simplest default composite value is the one which which is recursively default in all of its subfields. Given that predefined default values are a fixture in Java, this convention does not appear harmful, so we will adopt it.

As a result, the author of methods in a value type definition will need provide behavior to default (all-zero-bits) values, even if the constructors never create them, since they can be observed in some uninitialized variables. It is likely that we will either forbid no-argument constructors or require them to produce default values, to avoid “duelling defaults”.

a++
2  0 
Avatar de adiGuba
Expert éminent sénior https://www.developpez.com
Le 13/05/2014 à 20:02
Désolé mais je ne vois toujours pas l'intérêt du code, ni son rapport avec le sujet...

a++
2  0 
Avatar de thelvin
Modérateur https://www.developpez.com
Le 17/05/2014 à 22:06
What ?

- Assez verbeux : bon ça c'est dans sa nature, l'idée c'est qu'on peut pas ignorer ce qu'on fait quand on code. C'est pas parfait mais les résultats sont bons. Encore faut-il vouloir ça.
Mais les derniers ajouts qui y ont été faits, servent justement à le rendre moins verbeux. 'Faudrait savoir ce que tu veux.

- Peu performant : mais bien sûr, et t'as des preuves bien entendu.
L'aspect principal sur lequel Java est peu performant, c'est ce que la présente amélioration essaie d'enlever. À nouveau, 'faudrait savoir ce que tu veux.
Les autres aspects sur lesquels Java peut être peu performant si on les exploite vraiment à fond, sont inévitables pour son architecture sécurisée. Ils n'existent pas si on s'amuse à compiler du Java pour une architecture qui ne sécurise la cohérence du modèle mémoire. Donc encore, 'faudrait savoir ce que tu veux.

- Mal sécurisé : Ben voyons, et par comparaison avec quel autre langage/architecture ?
2  0 
Avatar de adiGuba
Expert éminent sénior https://www.developpez.com
Le 18/05/2014 à 10:34
Citation Envoyé par thelvin Voir le message
- Mal sécurisé : Ben voyons, et par comparaison avec quel autre langage/architecture ?
"Java c'est mal sécurisé", c'est le nouveau "Java c'est lent".

Un gros mythe qui s'installe au vue des différentes news catastrophiques sur les problèmes de sécurité des applets.
La plupart des gens n'arrivant pas à faire la distinction entre le plugin Java et le langage Java...

a++
2  0 
Avatar de Gugelhupf
Modérateur https://www.developpez.com
Le 08/05/2014 à 20:02
Les développeurs COBOL sont des vrais développeurs, mais... d'une autre époque on va dire... Et puis il y a :
  • des milliards de lignes de codes déjà fait en COBOL
  • des employés qui ne savent faire que du COBOL
  • des partenariats avec IBM

Comment remplacer cela par une autre solution du jour au lendemain ? Ce n'est tout bonnement pas possible. De plus, il me semble que :
  • niveau performance, ça doit surement être presque du même niveau qu'un binaire du C pour la conso CPU & mémoire.
  • certaines banques ont déjà mis en place des outils graphiques pour le développement (proche du diagramme d'activité UML), cela génère ensuite du script COBOL qui sera ensuite compilé et exécuté par le mainframe.


Pour en revenir au sujet, je sais que ce projet n'est qu'à ses balbutiements mais, au lieu d'avoir deux mots-clés pour créer une "value type" (ou "value class":
Code : Sélectionner tout
final __ByValue class Point { ...
Ils devraient plutôt faire usage du mot-clé "struct". Bien sur sa signification n'aura pas la même chose qu'en C ou C++, un peu comme l'a fait C# pour sa version du struct.

Je pense qu'une "value type" devrait pouvoir hériter d'une autre "value type", d'après eux ce n'est pas possible car :
Code : Sélectionner tout
Can a concrete value class extend another value type? No. (Because concrete value classes are final.)
Histoire de mutabilité...

Puis pour l'instanciation d'une "value type", ne pas utiliser le mot-clé "new" :
Code : Sélectionner tout
1
2
3
decimal salary1; // pas d'argument, constructeur par défaut
decimal salary2(); // ou bien
decimal salary3(100, 2);
Un peu comme en C++, sans le risque de confusion avec la déclaration de prototype de fonction.
1  0 
Avatar de la.lune
Membre chevronné https://www.developpez.com
Le 08/05/2014 à 20:40
Citation Envoyé par Gugelhupf Voir le message
C'est peut-être un début pour essayer de rendre Java un langage full object, les variables primitives Java deviendraient peut-être des classes, et peut-être que les Wrapper ne seront plus utilisés (j'ai lu quelques articles dans lequel on parle d'un Java 9 qui casse le backward compatibily...).
Bien sur coté performance il y aura certainement un impact négatif.
Pour ce qui est le fait de la mort des types primitifs c'est déjà tranché pour Java 10 et non 9, mais ça ne veut pas dire qu'on aura à faire des new pour déclarer des objets. Mais ce qui est sûr ce qui veulent entamer une chose pareil voient le vrai gain, mais pas pour faire juste pour faire beau.

Personnellement je ne vois pas d'impacte négatif au contraire je vois une très bonne chose car ça éviterait des casting insensé et permettre la généricité sur des "type primitif" comme vous savez qu'en Java on peut pas faire List<int> , du coup on fera forcement List<Interer> et des casting implicite ou explicites se passent, ou appel de méthodes pour manipuler les valeurs.

Surtout actuellement avec l'API Stream qu'on tend à éliminer les boucles d'itération sur les tableaux au profit de la programmation fonctionnelle et parallèle il faudra forcement une vraie innovation sur les types primitifs, car la manipulation des types primitifs avec Stream passent par les Wrappers, alors Java 10 permettra des gain en performance.

Citation Envoyé par Gugelhupf Voir le message
C'est peut-être un début pour essayer de rendre Java un langage full object
Les Value types si on comprend bien le challenge ils n'ont rien n'avoir avec le fait de transformer les types primitifs en en Objet. Au contraire ça va dans le sens contraire, on veut réduire et simplifier la manière d'utilisation de certains objets comme des valeurs primitifs et bien les organiser au niveau de la mémoire encore des gain.

J'avais pensé à côté de la plaque pour les exemples que j'avais donné
1  0 
Avatar de tchize_
Expert éminent sénior https://www.developpez.com
Le 08/05/2014 à 23:13
Citation Envoyé par Arsene Newman  Voir le message
[B]Par exemple, l’utilisateur définit en premier lieu une classe Point qui représente un point sur un plan 2D, en sachant que cette dernière ne sera pas « castée » en un autre objet.

Dommage le choix de l'exemple

Point, Point2D.Float, Point2D.Double, tous étendent Point2D et le typecasting arrive entre Point2D et Point2D.Double, parfois
1  0 
Avatar de thelvin
Modérateur https://www.developpez.com
Le 09/05/2014 à 1:20
Citation Envoyé par Cyäegha Voir le message
devoir utiliser l'opérateur "+" pour un int mais la méthode "add" pour un BigInt, sous prétexte que leur implémentation est différente, n'a pas vraiment de sens...
Et justement, ça n'a rien à voir avec les implémentations. C'est une question de définition du langage.

Il y a en Java, exactement 8 types primitifs. Pas moins, pas plus. 8. Pour certains d'entre eux, ça a un sens de prévoir un opérateur d'addition : double, float, long, int, short, byte et char. Pour d'autres, ça n'a pas de sens : boolean. Donc l'opérateur d'addition a été prévu pour les 7 types primitifs connus pour lesquels il a un sens, et pas pour les autres.

BigInteger, par contre, est une classe. Une classe comme une autre. Il y a en Java un nombre indéfini de classes, ça change tout le temps. De manière générale, par exemple dans le cas chien + facture, un opérateur d'addition n'a pas de sens entre deux types classe, ou objet de manière générale. Il n'y a donc pas eu tentative d'insérer dans le langage un opérateur qui, par définition, ne peut pas marcher. Les méthodes, en revanche, sont des mécanismes qu'on peut appliquer à tous les types objet, donc si on a un type additionnable, il suffit de lui donner une méthode add().
Il a été décidé pour le langage Java que la classe BigInteger, n'est pas si intéressante pour mériter d'être un cas particulier de sorte d'avoir un opérateur qui marche qu'avec elle. Même si ça avait été le cas, ça n'aurait pas résolu le besoin de nouvelles classes de nombres additionnables, dont Java ne pourrait pas deviner que ce sont des cas particuliers.
Certaines classes, en Java, sont spéciales. Les classes wrappers. La classe String. La classe Object, ascendante de tous les types objets. Il y a une méthode qui est un xas particulier, aussi, getClass(). Mais pas BigInteger ni son add().
1  0 
Avatar de thelvin
Modérateur https://www.developpez.com
Le 11/05/2014 à 1:28
Tu t'embrouilles vraiment à mort. Sans rire, il va falloir te mettre un peu au point avant de proposer des trucs pour la définition du langage Java -_-°.

Donc, oui null est la valeur par défaut du type String et de tous les types objets, c'est comme ça et on dit ça que ça te plaise ou non. Oui c'est aussi le fait de ne pointer vers aucun objet, donc la valeur par défaut du type String c'est de ne pas pointer vers un objet. Et alors ?
Chose impossible avec les types de base et valueTypes, d'où le problème original que j'évoquais, comment on leur donne une valeur par défaut puisque c'est pas null.

Ensuite et c'est là que les choses se compliquent, figure-toi que si, le tableau de char d'une String, tout comme toutes les variables membres, commence d'abord par avoir une valeur par défaut, null. Ensuite il est assigné une fois et une seule, comme imposé par son status de final, dans le constructeur.
Comme cette variable est final, le langage Java interdit de la lire en connaissance de cause avant qu'elle ait été assignée. Comme elle est aussi private, et que this n'est pas exposé dans le constructeur de String, il est très difficile de lire cette variable avant son assignation sans connaissance de cause. Difficile mais possible en théorie, en jouant sur les threads.
Le langage Java rend très compliqué de le voir, et on va pas s'en plaindre, on a pas envie de savoir qu'une variable final porte deux valeurs dans sa vie au lieu d'une. Mais le runtime qui applique le bytecode de la classe, lui, il est parfaitement au courant. Il doit d'abord allouer l'espace de l'objet et initialiser cet espace à des valeurs sûres. Ce qui, pour le tableau de chars, correspond à null. Sa valeur définitive arrivera plus tard, pendant le constructeur.
Et bien que cela n'ait rien à voir avec être final ou pas, les valueTypes, tout comme un tableau de char, devront être initialisés à des valeurs par défaut. La question que je me pose, c'est : comment on définira leur valeur par défaut ? C'est pas que ce soit si difficile d'imaginer comment le faire dans le langage, mais ça devrait être différent pour chaque valueType. La JVM chargée de charger la classe, va donc devoir savoir, quand une classe contient une variable de type valueType, comment lui définir une valeur par défaut. Et là ça devient contradictoire avec les principes passés, d'une manière ou d'une autre.
1  0