DZone
Java Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Java Zone > The depths of Java: API leak exposed through covariance

The depths of Java: API leak exposed through covariance

Lukas Eder user avatar by
Lukas Eder
·
Feb. 09, 12 · Java Zone · Interview
Like (0)
Save
Tweet
4.60K Views

Join the DZone community and get the full member experience.

Join For Free

java can be very tricky some times, especially in api design. let’s have a look at a very interesting showcase. jooq strongly separates api from implementation. all api is in the org.jooq package, and public. most implementation is in the org.jooq.impl package and package-private. only factories and some dedicated base implementations are public. this allows for very powerful package-level encapsulation, exposing mostly only interfaces to jooq users.

a simplified example of package-level encapsulation

here’s roughly how jooq models sql tables. the (overly simplified) api:

package org.jooq;

/**
 * a table in a database
 */
public interface table {

  /**
   * join two tables
   */
  table join(table table);
}

and two (overly simplified) implementation classes:

package org.jooq.impl;

import org.jooq.table;

/**
 * base implementation
 */
abstract class abstracttable implements table {

  @override
  public table join(table table) {
    return null;
  }
}

/**
 * custom implementation, publicly exposed to client code
 */
public class customtable extends abstracttable {
}

how the internal api is exposed

let’s assume that the internal api does some tricks with covariance:

abstract class abstracttable implements table, interalstuff {

  // note, this method returns abstracttable, as it might
  // prove to be convenient to expose some internal api
  // facts within the internal api itself
  @override
  public abstracttable join(table table) {
    return null;
  }

  /**
   * some internal api method, also package private
   */
  void dothings() {}
  void domorethings() {

    // use the internal api
    join(this).dothings();
  }
}

this looks all safe at the first sight, but is it? abstracttable is package-private, but customtable extends it and inherits all of its api, including the covariant method override of “abstracttable join(table)”. what does that result in? check out the following piece of client code

package org.jooq.test;

import org.jooq.table;
import org.jooq.impl.customtable;

public class test {
  public static void main(string[] args) {
    table joined = new customtable();

    // this works, no knowledge of abstracttable exposed to the compiler
    table table1 = new customtable();
    table join1 = table1.join(joined);

    // this works, even if join exposes abstracttable
    customtable table2 = new customtable();
    table join2 = table2.join(joined);

    // this doesn't work. the type abstracttable is not visible
    table join3 = table2.join(joined).join(joined);
    //            ^^^^^^^^^^^^^^^^^^^ this cannot be dereferenced

    // ... so hide these implementation details again
    // the api flaw can be circumvented with casting
    table join4 = ((table) table2.join(joined)).join(joined);
  }
}

conclusion

tampering with visibilities in class hierarchies can be dangerous. beware of the fact that api methods declared in interfaces are always public, regardless of any covariant implementations that involve non-public artefacts. this can be quite annoying for api users when not properly dealt with by api designers.

fixed in the next version of jooq :-)

from http://lukaseder.wordpress.com/2012/02/03/the-depths-of-java-api-leak-exposed-through-covariance/

API Java (programming language) Covariance

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • How To Evaluate Software Quality Assurance Success: KPIs, SLAs, Release Cycles, and Costs
  • Modern Application Security Requires Defense in Depth
  • Java Microservices: Code Examples, Tutorials, and More
  • SQL GROUP BY and Functional Dependencies: a Very Useful Feature

Comments

Java Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo