Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

6521141: DebugGraphics NPE @ setFont(); #9673

Closed
wants to merge 22 commits into from

Conversation

TejeshR13
Copy link
Contributor

@TejeshR13 TejeshR13 commented Jul 28, 2022

DebugGraphics class has a Graphics instance which is been used in slowed down drawing. The graphics object is not initialized anywhere inside the class, where it is expected to set explicitly by the user. When the user doesn't set it and try to use the any mehtods like drawing/setFont, NPE is raised which is expected. The scenario is taken care by checking if the graphics object is null before using it inside the class, thus eliminating the NPE case.


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change requires a CSR request to be approved

Issues

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/9673/head:pull/9673
$ git checkout pull/9673

Update a local copy of the PR:
$ git checkout pull/9673
$ git pull https://git.openjdk.org/jdk pull/9673/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 9673

View PR using the GUI difftool:
$ git pr show -t 9673

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/9673.diff

@bridgekeeper
Copy link

bridgekeeper bot commented Jul 28, 2022

👋 Welcome back tr! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Jul 28, 2022

⚠️ @TejeshR13 This pull request contains merges that bring in commits not present in the target repository. Since this is not a "merge style" pull request, these changes will be squashed when this pull request in integrated. If this is your intention, then please ignore this message. If you want to preserve the commit structure, you must change the title of this pull request to Merge <project>:<branch> where <project> is the name of another project in the OpenJDK organization (for example Merge jdk:master).

@openjdk openjdk bot added the rfr Pull request is ready for review label Jul 28, 2022
@openjdk
Copy link

openjdk bot commented Jul 28, 2022

@TejeshR13 The following label will be automatically applied to this pull request:

  • client

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the client client-libs-dev@openjdk.org label Jul 28, 2022
@mlbridge
Copy link

mlbridge bot commented Jul 28, 2022

Copy link
Contributor

@prsadhuk prsadhuk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess exposing no-args public constructor was wrong and it should have been protected from beginning.
Also, please add a testcase.

" Setting clipRect: " + (new Rectangle(x, y, width, height)) +
" New clipRect: " + graphics.getClip());
" Setting clipRect: " + (new Rectangle(x, y, width, height)) +
" New clipRect: " + graphics.getClip());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this line change is needed? Probably you have added some tabs..Remove this change and similarly from other logs down below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think auto indentation has caused this, will undo these tabs changes.

@TejeshR13
Copy link
Contributor Author

I guess exposing no-args public constructor was wrong and it should have been protected from beginning. Also, please add a testcase.

Yeah, its been used internally by other constructors after setting the graphics instances. Exposing it as public causes user to create it without graphics been set. I tried modifying it to protected and ran the test, but some html test fails.

@kevinrushforth
Copy link
Member

I guess exposing no-args public constructor was wrong and it should have been protected from beginning. Also, please add a testcase.

Yeah, its been used internally by other constructors after setting the graphics instances. Exposing it as public causes user to create it without graphics been set. I tried modifying it to protected and ran the test, but some html test fails.

Even if it hadn't failed the test, you cannot simply change a method, constructor, or field in a public (or protected) class in an exported package from public to protected, since that would be an incompatible API change (at least not without a very compelling reason and a lot of discussion, and even then, probably not).

@TejeshR13
Copy link
Contributor Author

I guess exposing no-args public constructor was wrong and it should have been protected from beginning. Also, please add a testcase.

Yeah, its been used internally by other constructors after setting the graphics instances. Exposing it as public causes user to create it without graphics been set. I tried modifying it to protected and ran the test, but some html test fails.

Even if it hadn't failed the test, you cannot simply change a method, constructor, or field in a public (or protected) class in an exported package from public to protected, since that would be an incompatible API change (at least not without a very compelling reason and a lot of discussion, and even then, probably not).

Yeah, sure @kevinrushforth.

@openjdk openjdk bot removed the rfr Pull request is ready for review label Jul 28, 2022
@openjdk openjdk bot added the rfr Pull request is ready for review label Jul 28, 2022
@prrace
Copy link
Contributor

prrace commented Jul 28, 2022

You wrote " The graphics object is not initialized anywhere inside the class, where it is expected to set explicitly by the user. "

which reads a bit like if the user does
DebugGraphics dg = new DebugGraphics();
they must then follow it up with
dg.setGraphics(g);
however there's no such method.

So any DebugGraphics created this way is useless.
You can't use it for debugging
Making it protected won't prevent mis-use.
Someone could subclass and provide a public no-args constructor and the problem will recur.

The javadoc for the class says :
DebugGraphics objects are rarely created by hand

So likely no one should be doing this.

I'd just add javadoc saying "This constructor should not be called by applications, it
is for internal use only. When called directly it will create an un-usable instance".

The only other thing I can think of is to try to figure out by using
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/StackWalker.html#getCallerClass())

if it was called from outside DebugGraphics, and if so install some other graphics instead.

something like ..
if (graphics == null && stackWalker.getCallerClass() != this.class ) {
BufferedImage bi = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB);
graphics = bi.createGraphics();
}

@TejeshR13
Copy link
Contributor Author

Yeah, this looks like a better idea @prrace. I will update the java doc and also will create the BufferedImage graphics from the no-arg constructor. With this we will be warning about the usage of no-arg constructor to user and also handle NPE cases.

// Creates a Graphics context when Application calls the constructor
// directly.
StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
if ((graphics == null) && (walker.getCallerClass() != this.getClass())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if creating a StackWalker is expensive but I think it should be done only if graphics == null

Also the version of getInstance() being called here might throw SecurityException
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/StackWalker.html#getInstance(java.lang.StackWalker.Option)

So you'll need to wrap it in a doPrivileged.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking only if graphics == null will also handle the case when user sets the graphics to null by passing null in the constructor, so removing StackWalker and checking only for graphics == null will handle both the cases whether its internal class or called from other class.

Copy link
Contributor Author

@TejeshR13 TejeshR13 Aug 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@prrace Then I will proceed by removing Stackwalker and create a graphics instance only if its null.

Copy link
Contributor

@prrace prrace Aug 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because that won't work, or more precisely will be a waste of work.
See
DebugGraphics(Graphics graphics) {
this(); // << no-args constructor and graphics will still be null
this.graphics = null;
}

graphics will ALWAYS be null when you come via here which is exactly why we needed StackWalker

Copy link
Contributor Author

@TejeshR13 TejeshR13 Aug 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then we should set graphics only If the no-args constructor is called by another program and not via by the same class. I had understood the previous suggestion wrongly, now I got it. We are supposed to create instance of stackwalker only if graphics is null and wrap it around doPrivileged.

@openjdk openjdk bot added the csr Pull request needs approved CSR before integration label Aug 1, 2022
}
});

if(walker.getCallerClass() != this.getClass()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add space after if

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

@@ -72,11 +74,32 @@ public class DebugGraphics extends Graphics {
/**
* Constructs a new debug graphics context that supports slowed
* down drawing.
* <p>
* NOTE: This constructor should not be called by
* application, it is for Internal use only. When called directly
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"application" -> "applications"
"Internal" -> "internal"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.


/* @test
* @bug 6521141
* @key headful
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this test need to be headful ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually not required, since no UI is used..... Will remove and test......

@TejeshR13
Copy link
Contributor Author

@prrace, I have updated the PR, let me know if its ok now......

*/
public class DebugGraphicsNPETest {
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need of using EDT here as no Swing components in used. You can just move runTest() lines in main..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah right. I have updated the test @prsadhuk

public DebugGraphics() {
super();
buffer = null;
xOffset = yOffset = 0;

// Creates a Graphics context when the constructor is called.
if (graphics == null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably it will be better to use this.graphics here and below while setting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated @prsadhuk .

@openjdk openjdk bot removed the csr Pull request needs approved CSR before integration label Aug 11, 2022
@openjdk
Copy link

openjdk bot commented Aug 11, 2022

@TejeshR13 This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

6521141: DebugGraphics NPE @ setFont();

Reviewed-by: prr

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 329 new commits pushed to the master branch:

  • 083e014: 8292233: Increase symtab hash table size
  • 45e5b31: 8292244: Remove unnecessary include directories
  • 9bfffa0: 8291945: Add OSInfo API for static OS information
  • bd58553: 8290833: Remove ConstantPoolCache::walk_entries_for_initialization()
  • 755ecf6: 8292153: x86: Represent Registers as values
  • dedc05c: 8291640: java/beans/XMLDecoder/8028054/Task.java should use the 3-arg Class.forName
  • 3d20a8b: 8291959: FileFontStrike#initNative does not properly initialize IG Table on Windows
  • a28ab7b: 8288568: Reduce runtime of java.security microbenchmarks
  • 7ea9ba1: 8292064: Convert java/lang/management/MemoryMXBean shell tests to java version
  • fc1d94e: 8292232: AIX build failure by JDK-8290840
  • ... and 319 more: https://git.openjdk.org/jdk/compare/c7c20661eee727ed8354b19723c359ae7c2d4bd8...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@prsadhuk, @prrace) but any other Committer may sponsor as well.

➡️ To flag this PR as ready for integration with the above commit message, type /integrate in a new comment. (Afterwards, your sponsor types /sponsor in a new comment to perform the integration).

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Aug 11, 2022
@TejeshR13
Copy link
Contributor Author

/integrate

@openjdk openjdk bot added the sponsor Pull request is ready to be sponsored label Aug 12, 2022
@openjdk
Copy link

openjdk bot commented Aug 12, 2022

@TejeshR13
Your change (at version cedaa2f) is now ready to be sponsored by a Committer.

@prsadhuk
Copy link
Contributor

/sponsor

@openjdk
Copy link

openjdk bot commented Aug 16, 2022

Going to push as commit 21f4eb2.
Since your change was applied there have been 353 commits pushed to the master branch:

  • 6e6ae59: 8292286: Convert PlaceholderTable to ResourceHashtable
  • ea2c82e: 8291949: Unexpected extending of SupportedGroups
  • b5707b0: 8292196: Reduce runtime of java.util.regex microbenchmarks
  • b00eede: 8291511: Redefinition of EXIT_FAILURE in libw2k_lsa_auth
  • 3a09077: 8291337: Reduce runtime of vm.lamdba microbenchmarks
  • dd2034b: 8291972: Fix double copy of arguments when thawing two interpreted frames
  • aa5b718: 8292182: [TESTLIB] Enhance JAXPPolicyManager to setup required permissions for jtreg version 7 jar
  • 695bb39: 8292347: Remove unused Type::is_ptr_to_boxing_obj
  • ec96b1f: 8290291: G1: Merge multiple calls of block_size in HeapRegion::block_start
  • fd4b2f2: 8291718: Remove mark_for_deoptimization from klass unloading
  • ... and 343 more: https://git.openjdk.org/jdk/compare/c7c20661eee727ed8354b19723c359ae7c2d4bd8...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Aug 16, 2022
@openjdk openjdk bot closed this Aug 16, 2022
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review sponsor Pull request is ready to be sponsored labels Aug 16, 2022
@openjdk
Copy link

openjdk bot commented Aug 16, 2022

@prsadhuk @TejeshR13 Pushed as commit 21f4eb2.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client client-libs-dev@openjdk.org integrated Pull request has been integrated
6 participants