You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@thrift.apache.org by "Garret Wilson (JIRA)" <ji...@apache.org> on 2019/05/03 17:00:00 UTC
[jira] [Updated] (THRIFT-4857) Java field hash code implementation
inconsistent with equals.
[ https://issues.apache.org/jira/browse/THRIFT-4857?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Garret Wilson updated THRIFT-4857:
----------------------------------
Description:
The {{TField}} hash code implementation is inconsistent with equals, which is a breaking bug. If you know what hash codes are and are familiar with the Java {{Object}} API, then you already know what I'm talking about. Basically Java _requires_ that, if you override {{hashCode()}} and {{equals()}}, then for any two objects that are equals they _must_ return the same has code.
The {{TField}} class API contract isn't clear about what is considered equality, but according to the {{TField.equals()}} implementation, fields are equal if and only if:
* Both objects are a {{TField}} (I'm generalizing here; there's another subtle bug lurking with class checking, but that's another story).
* The fields both have the same {{type}} and {{id}}.
In other words, fields are equal _without regard to name_. And this follows the overall Thrift architecture, in which field names are little more than window dressing, and the IDs carry the semantics.
Unfortunately {{TField.hashCode()}} includes the name in the hash code calculation! This completely breaks the {{Object}} contract. It makes the hash code inconsistent with equality. To put it another way, two fields {{foo}} and {{bar}} could have the same type and ID, and {{foo.equals(bar)}} would return {{true}}, but they would be given different hash codes!!
This is completely forbidden, and means that with this bug you cannot use a {{TField}} as the key in a map, for example, or even keep a {{Set<TField>}} of fields! If you were to store {{foo}} and {{bar}} as keys in a map, for example, the different hash codes would put them in different buckets, even though they were considered equal, providing inconsistent and strange lookup results, depending on the name of the field you used to query with.
This is simply broken as per the Java {{Object}} API contract.
was:
The {{TField}} hash code implementation is inconsistent with equals, which is a breaking bug. If you know what hash codes are and are familiar with the Java {{Object}} API, then you already know what I'm talking about. Basically Java _requires_ that, if you override {{hashCode()}} and {{equals()}}, then for any two objects that are equals they _must_ return the same has code.
The {{TField}} class API contract isn't clear about what is considered equality, but according to the {{TField.equals()}} implementation, fields are equal if and only if:
* Both objects are a {{TField}} (I'm generalizing here; there's another subtle bug lurking with class checking, but that's another story).
* The fields both have the same {{type}} and {{id}}.
In other words, fields are equal _without regard to name_. And this follows the overall Thrift architecture, in which field names are little more than window dressing, and the IDs carry the semantics.
Unfortunately {{TField.hashCode()}} includes the name in the hash code calculation! This completely breaks the {{Object}} contract. It makes the hash code inconsistent with equality. To put it another way, two fields {{foo}} and {{bar}} could have the same type and ID, and {{foo.equals(bar)}} would return {{true}}, but they would be given different hash codes!!
This is completely forbidden, and means that with this bug you cannot use a {{TField}} as the key in a map, for example, or even keep a {{Set<TField>}} of fields! If you were to store {{foo} and {{bar}} as keys in a map, for example, the different hash codes would put them in different buckets, even though they were considered equal, providing inconsistent and strange lookup results, depending on the name of the field you used to query with.
This is simply broken as per the Java {{Object}} API contract.
> Java field hash code implementation inconsistent with equals.
> -------------------------------------------------------------
>
> Key: THRIFT-4857
> URL: https://issues.apache.org/jira/browse/THRIFT-4857
> Project: Thrift
> Issue Type: Bug
> Components: Java - Library
> Affects Versions: 0.12.0
> Reporter: Garret Wilson
> Priority: Major
>
> The {{TField}} hash code implementation is inconsistent with equals, which is a breaking bug. If you know what hash codes are and are familiar with the Java {{Object}} API, then you already know what I'm talking about. Basically Java _requires_ that, if you override {{hashCode()}} and {{equals()}}, then for any two objects that are equals they _must_ return the same has code.
> The {{TField}} class API contract isn't clear about what is considered equality, but according to the {{TField.equals()}} implementation, fields are equal if and only if:
> * Both objects are a {{TField}} (I'm generalizing here; there's another subtle bug lurking with class checking, but that's another story).
> * The fields both have the same {{type}} and {{id}}.
> In other words, fields are equal _without regard to name_. And this follows the overall Thrift architecture, in which field names are little more than window dressing, and the IDs carry the semantics.
> Unfortunately {{TField.hashCode()}} includes the name in the hash code calculation! This completely breaks the {{Object}} contract. It makes the hash code inconsistent with equality. To put it another way, two fields {{foo}} and {{bar}} could have the same type and ID, and {{foo.equals(bar)}} would return {{true}}, but they would be given different hash codes!!
> This is completely forbidden, and means that with this bug you cannot use a {{TField}} as the key in a map, for example, or even keep a {{Set<TField>}} of fields! If you were to store {{foo}} and {{bar}} as keys in a map, for example, the different hash codes would put them in different buckets, even though they were considered equal, providing inconsistent and strange lookup results, depending on the name of the field you used to query with.
> This is simply broken as per the Java {{Object}} API contract.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)