Java API to find out the JDK version a class file is compiled for? - version

Are there any Java APIs to find out the JDK version a class file is compiled for? Of course there is the javap tool to find out the major version as mentioned in here. However I want to do it programmatically so that that I could warn the user to compile it for the appropriate JDK

import java.io.*;
public class ClassVersionChecker {
public static void main(String[] args) throws IOException {
for (int i = 0; i < args.length; i++)
checkClassVersion(args[i]);
}
private static void checkClassVersion(String filename)
throws IOException
{
DataInputStream in = new DataInputStream
(new FileInputStream(filename));
int magic = in.readInt();
if(magic != 0xcafebabe) {
System.out.println(filename + " is not a valid class!");;
}
int minor = in.readUnsignedShort();
int major = in.readUnsignedShort();
System.out.println(filename + ": " + major + " . " + minor);
in.close();
}
}
The possible values are :
major minor Java platform version
45 3 1.0
45 3 1.1
46 0 1.2
47 0 1.3
48 0 1.4
49 0 5
50 0 6
51 0 7
52 0 8
53 0 9
54 0 10
55 0 11
56 0 12
57 0 13
58 0 14
59 0 15
60 0 16
61 0 17
62 0 18
63 0 19
ref : The Java Virtual Machine Specification, Java SE 19 Edition

basszero's approach can be done via the UNIX command line, and the "od(1)" command:
% od -x HelloWorldJava.class |head -2
0000000 feca beba 0000 3100 dc00 0007 0102 2a00
0000020 6f63 2f6d 6e65 6564 6163 642f 6d65 2f6f
"feca beba" is the magic number. The "0000 3100" is 0x31, which represents J2SE 5.0.

On Linux, you can use the file command on a class file, which I found easiest for my use case. For example:
$ file Foo.class
Foo.class: compiled Java class data, version 50.0 (Java 1.6)

Apache BCEL provides this API:
JavaClass c = Repository.lookupClass("com.x.MyClass")
c.getMinor();
c.getMajor();

This gets you the contents of the class file:
MysteryClass.class.getResourceAsStream("MysteryClass.class")
Then look at bytes 5-8 to get the minor and major version. A mapping between those numbers and the JDK releases can be found here.

Just read the class file directly. It's VERY easy to figure out the version. Check out the the spec and wiki and then try the code. Wrapping this code and making is more useful/pretty is left as an exercise. Alternatively, you could use a library like BCEL, ASM, or JavaAssist
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ClassVersionTest
{
private static final int JAVA_CLASS_MAGIC = 0xCAFEBABE;
public static void main(String[] args)
{
try
{
DataInputStream dis = new DataInputStream(new FileInputStream("Test.class"));
int magic = dis.readInt();
if(magic == JAVA_CLASS_MAGIC)
{
int minorVersion = dis.readUnsignedShort();
int majorVersion = dis.readUnsignedShort();
/**
* majorVersion is ...
* J2SE 6.0 = 50 (0x32 hex),
* J2SE 5.0 = 49 (0x31 hex),
* JDK 1.4 = 48 (0x30 hex),
* JDK 1.3 = 47 (0x2F hex),
* JDK 1.2 = 46 (0x2E hex),
* JDK 1.1 = 45 (0x2D hex).
*/
System.out.println("ClassVersionTest.main() " + majorVersion + "." + minorVersion);
}
else
{
// not a class file
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

As others have shown, it is easy enough to do by reading the first eight bytes of a class file. If you want a pre-built binary library, you can download one here.

JavaP does have an API, but it's specific to the Sun JDK.
It's found in tools.jar, under sun/tools/javap/Main.class.

I use this script in a batch file on windows, redirect the output and grep for the major number I am verifying for:
for /R %%f in (*.class) do (
"C:\Program Files\Java\JDK8\bin\javap" -v "%%f" | findstr major )
I run it as such:
verify.bat > versionResults.txt

Related

Vulkan swapchain creation causes crash with no debug information

I'm following vulkan-tutorial's procedure to understand vulkan, I'm now in creating swapchain. before that I've also created instance and a debug/validation layer but when I'm trying to create swapchain, the app crashes.
void createSwapChain() {
VkSurfaceFormatKHR surfaceFormat;
surfaceFormat.format=VK_FORMAT_B8G8R8A8_SRGB;
surfaceFormat.colorSpace=VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
VkPresentModeKHR presentMode=VK_PRESENT_MODE_FIFO_KHR;
int width,height;
glfwGetFramebufferSize(window, &width, &height);
VkExtent2D extent ={width,height};
uint32_t imageCount=2;//minimum cap +1
VkSurfaceCapabilitiesKHR capabilities;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities);
VkSwapchainCreateInfoKHR createInfo={0};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = surface;
createInfo.minImageCount = imageCount;
createInfo.imageFormat = surfaceFormat.format;
createInfo.imageColorSpace = surfaceFormat.colorSpace;
createInfo.imageExtent = extent;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
// createInfo.queueFamilyIndexCount = 1;
// createInfo.pQueueFamilyIndices = NULL;
createInfo.preTransform = capabilities.currentTransform/*VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR*/;//swapChainSupport.capabilities.currentTransform
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = presentMode;
createInfo.clipped = VK_TRUE;// means obscured images have unimportant color!!
createInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(device, &createInfo, NULL, &swapChain) != VK_SUCCESS)
printf("failed to create swap chain!");
}
Is there any idea? The host is eclipse with MinGW-64 -lglfw3 and -lvulkan-1 on windows 10 64-bit.
And here the graphic card information:
Available Layers:
VK_LAYER_AMD_switchable_graphics
VK_LAYER_VALVE_steam_overlay
VK_LAYER_VALVE_steam_fossilize
VK_LAYER_KHRONOS_validation
Available extensions:
VK_KHR_device_group_creation
VK_KHR_external_fence_capabilities
VK_KHR_external_memory_capabilities
VK_KHR_external_semaphore_capabilities
VK_KHR_get_physical_device_properties2
VK_KHR_get_surface_capabilities2
VK_KHR_surface
VK_KHR_win32_surface
VK_EXT_debug_report
VK_EXT_debug_utils
VK_EXT_swapchain_colorspace
Instance extension:
VK_KHR_surface
VK_KHR_win32_surface
VK_EXT_debug_utils
Availible devices:
AMD Radeon(TM) Graphics Type: 1 GeometryShader: Yes
FamilyIndex: 0 AvailibleQueueCount: 1 Surface Support: Yes Graphics | Compute | Transfer | Binding
FamilyIndex: 1 AvailibleQueueCount: 2 Surface Support: Yes | Compute | Transfer | Binding
FamilyIndex: 2 AvailibleQueueCount: 1 Surface Support: Yes | | Transfer | Binding
Availible device extensions: (The required is VK_KHR_swapchain)
VK_KHR_16bit_storage VK_KHR_8bit_storage VK_KHR_bind_memory2
VK_KHR_buffer_device_address VK_KHR_copy_commands2 VK_KHR_create_renderpass2
VK_KHR_dedicated_allocation VK_KHR_depth_stencil_resolve VK_KHR_descriptor_update_template
VK_KHR_device_group VK_KHR_draw_indirect_count VK_KHR_driver_properties
VK_KHR_dynamic_rendering VK_KHR_external_fence VK_KHR_external_fence_win32
VK_KHR_external_memory VK_KHR_external_memory_win32 VK_KHR_external_semaphore
VK_KHR_external_semaphore_win32 VK_KHR_format_feature_flags2 VK_KHR_get_memory_requirements2
VK_KHR_global_priority VK_KHR_imageless_framebuffer VK_KHR_image_format_list
VK_KHR_maintenance1 VK_KHR_maintenance2 VK_KHR_maintenance3
VK_KHR_maintenance4 VK_KHR_multiview VK_KHR_pipeline_executable_properties
VK_KHR_pipeline_library VK_KHR_push_descriptor VK_KHR_relaxed_block_layout
VK_KHR_sampler_mirror_clamp_to_edge VK_KHR_sampler_ycbcr_conversion VK_KHR_separate_depth_stencil_layouts
VK_KHR_shader_atomic_int64 VK_KHR_shader_clock VK_KHR_shader_draw_parameters
VK_KHR_shader_float16_int8 VK_KHR_shader_float_controls VK_KHR_shader_integer_dot_product
VK_KHR_shader_non_semantic_info VK_KHR_shader_subgroup_extended_types VK_KHR_shader_subgroup_uniform_control_flow
VK_KHR_shader_terminate_invocation VK_KHR_spirv_1_4 VK_KHR_storage_buffer_storage_class
Swap chain details:
Min/max images in swap chain; 1, 16
Min/max width and height 800 : 600 | 800 : 600
Pixel format codes(at least we need one no matter what!): 44
50 58 97 44 50 58 97 58 97 58
97 97 2 3 4 5 8 37 38 43
45 51 52 57 64 91 92 122
color space codes(at least we need one no matter what!): 0
0 0 0 1000104006 1000104006 1000104006 1000104006 1000104008 1000104008 1000104007
1000104007 1000104002 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Available presentation modes:
0 (Immediate)
2 3 ( FIFO, FIFO_relaxed)
A few things:
There isn't really enough information in the problem description to allow others to locate the problem. For example, we can't tell how surface got created and we can't tell how the Vulkan device got created. It is better to post a complete reproducible example someplace and point to it.
There are a lot of hits when searching for "vulkan swapchain exception" like this one and this one. Something there may give a clue.
Based on what is provided and the links mentioned above, my best guess is that you're not enabling the swapchain extension when creating the device. Perhaps you could check that?
The validation layer should be helpful and you can find more information about it here. You might try making a vk_layer_settings.txt file and use it to set the message severity to "info" so that you can verify that the layer is active. (It will print some sort of startup message at this level) Your IDE might be swallowing the text output coming from the validation layer and the point behind doing this is to verify that you can see any validation output. It may be easier to provide a log filename in the same settings file to send the validation output to that file instead of figuring out what the IDE is doing. You can also use the vkconfig tool to apply these sorts of settings to the validation layer.

My H2/C3PO/Hibernate setup does not seem to preserving prepared statements?

I am finding my database is the bottleneck in my application, as part of this it looks like Prepared statements are not being reused.
For example here method I use
public static CoverImage findCoverImageBySource(Session session, String src)
{
try
{
Query q = session.createQuery("from CoverImage t1 where t1.source=:source");
q.setParameter("source", src, StandardBasicTypes.STRING);
CoverImage result = (CoverImage)q.setMaxResults(1).uniqueResult();
return result;
}
catch (Exception ex)
{
MainWindow.logger.log(Level.SEVERE, ex.getMessage(), ex);
}
return null;
}
But using Yourkit profiler it says
com.mchange.v2.c3po.impl.NewProxyPreparedStatemtn.executeQuery() Count 511
com.mchnage.v2.c3po.impl.NewProxyConnection.prepareStatement() Count 511
and I assume that the count for prepareStatement() call should be lower, ais it is looks like we create a new prepared statment every time instead of reusing.
https://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html
I am using C3po connecting poolng wehich complicates things a little, but as I understand it I have it configured correctly
public static Configuration getInitializedConfiguration()
{
//See https://www.mchange.com/projects/c3p0/#hibernate-specific
Configuration config = new Configuration();
config.setProperty(Environment.DRIVER,"org.h2.Driver");
config.setProperty(Environment.URL,"jdbc:h2:"+Db.DBFOLDER+"/"+Db.DBNAME+";FILE_LOCK=SOCKET;MVCC=TRUE;DB_CLOSE_ON_EXIT=FALSE;CACHE_SIZE=50000");
config.setProperty(Environment.DIALECT,"org.hibernate.dialect.H2Dialect");
System.setProperty("h2.bindAddress", InetAddress.getLoopbackAddress().getHostAddress());
config.setProperty("hibernate.connection.username","jaikoz");
config.setProperty("hibernate.connection.password","jaikoz");
config.setProperty("hibernate.c3p0.numHelperThreads","10");
config.setProperty("hibernate.c3p0.min_size","1");
//Consider that if we have lots of busy threads waiting on next stages could we possibly have alot of active
//connections.
config.setProperty("hibernate.c3p0.max_size","200");
config.setProperty("hibernate.c3p0.max_statements","5000");
config.setProperty("hibernate.c3p0.timeout","2000");
config.setProperty("hibernate.c3p0.maxStatementsPerConnection","50");
config.setProperty("hibernate.c3p0.idle_test_period","3000");
config.setProperty("hibernate.c3p0.acquireRetryAttempts","10");
//Cancel any connection that is more than 30 minutes old.
//config.setProperty("hibernate.c3p0.unreturnedConnectionTimeout","3000");
//config.setProperty("hibernate.show_sql","true");
//config.setProperty("org.hibernate.envers.audit_strategy", "org.hibernate.envers.strategy.ValidityAuditStrategy");
//config.setProperty("hibernate.format_sql","true");
config.setProperty("hibernate.generate_statistics","true");
//config.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
//config.setProperty("hibernate.cache.use_second_level_cache", "true");
//config.setProperty("hibernate.cache.use_query_cache", "true");
addEntitiesToConfig(config);
return config;
}
Using H2 1.3.172, Hibernate 4.3.11 and the corresponding c3po for that hibernate version
With reproducible test case we have
HibernateStats
HibernateStatistics.getQueryExecutionCount() 28
HibernateStatistics.getEntityInsertCount() 119
HibernateStatistics.getEntityUpdateCount() 39
HibernateStatistics.getPrepareStatementCount() 189
Profiler, method counts
GooGooStaementCache.aquireStatement() 35
GooGooStaementCache.checkInStatement() 189
GooGooStaementCache.checkOutStatement() 189
NewProxyPreparedStatement.init() 189
I don't know what I shoud be counting as creation of prepared statement rather than reusing an existing prepared statement ?
I also tried enabling c3p0 logging by adding a c3p0 logger ands making it use same log file in my LogProperties but had no effect.
String logFileName = Platform.getPlatformLogFolderInLogfileFormat() + "songkong_debug%u-%g.log";
FileHandler fe = new FileHandler(logFileName, LOG_SIZE_IN_BYTES, 10, true);
fe.setEncoding(StandardCharsets.UTF_8.name());
fe.setFormatter(new com.jthink.songkong.logging.LogFormatter());
fe.setLevel(Level.FINEST);
MainWindow.logger.addHandler(fe);
Logger c3p0Logger = Logger.getLogger("com.mchange.v2.c3p0");
c3p0Logger.setLevel(Level.FINEST);
c3p0Logger.addHandler(fe);
Now that I have eventually got c3p0Based logging working and I can confirm the suggestion of #Stevewaldman is correct.
If you enable
public static Logger c3p0ConnectionLogger = Logger.getLogger("com.mchange.v2.c3p0.stmt");
c3p0ConnectionLogger.setLevel(Level.FINEST);
c3p0ConnectionLogger.setUseParentHandlers(false);
Then you get log output of the form
24/08/2019 10.20.12:BST:FINEST: com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache ----> CACHE HIT
24/08/2019 10.20.12:BST:FINEST: checkoutStatement: com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache stats -- total size: 347; checked out: 1; num connections: 13; num keys: 347
24/08/2019 10.20.12:BST:FINEST: checkinStatement(): com.mchange.v2.c3p0.stmt.DoubleMaxStatementCache stats -- total size: 347; checked out: 0; num connections: 13; num keys: 347
making it clear when you get a cache hit. When there is no cache hit yo dont get the first line, but get the other two lines.
This is using C3p0 9.2.1

How to remove unnecessary parsing related info from Tika parsing output

I am parsing docx file with Apache Tika. Parsing is working file expect that it also prints some unnecessary texts in the beginning like below:
[Content_Types] .xml _rels / .rels word / _rels / document.xml.rels
word / document.xml
and at the end like below:
word / theme / theme1.xml word / settings.xml word / fontTable.xml
word / webSettings.xml docProps / app.xml Normal 13 3 460 2627
Microsoft Office Word 0 21 6 false XXXX XXXX false 3081 false false
12.0000 docProps / core. xml XXX XXXX 1 2016- 12-16T14: 57: 00Z 2016-12-16T15: 10: 00Z word / styles.xml
Code is :
public static String extractString(File file)
{
BodyContentHandler handler = new BodyContentHandler();
AutoDetectParser parser = new AutoDetectParser();
Metadata metadata = new Metadata();
try (InputStream stream = new FileInputStream(file))
{
parser.parse(stream, handler, metadata);
return handler.toString();
}
catch (IOException | SAXException | TikaException e)
{
e.printStackTrace();
return null;
}
}
How to remove the unnecessary crap from the beginning and end?

Autofixture: Issue when creating value types

Debugging with xUnit.net the test-methods Test1 and Test2 of the following code and putting a breakpoint and the end of CreateValueAndReferenceType() you see that the variable valueType is the same in both runs, whereas the variable referenceType is altered. The former is for me surprising and an issue as well (I added the row with the string-type only for completeness).
public class MyFixture : Fixture
{
public void CreateValueAndReferenceType()
{
var valueType = this.Create<int>();
var referenceTye = this.Create<string>();
}
}
public class TestClass1
{
[Fact]
public void Test1()
{
var myFixture = new MyFixture();
myFixture.CreateValueAndReferenceType();
}
}
public class TestClass2
{
[Fact]
public void Test2()
{
var myFixture = new MyFixture();
myFixture.CreateValueAndReferenceType();
}
}
What you're seeing is, I think, a basic issue related to pseudo-random number generation in .NET (IIRC, other platforms have similar issues). In essence, System.Random is deterministic, but initialised with a random seed that, among other things, depend on the computer's current time. If you create instances of Random in a tight loop, the code executes faster than the precision of the system clock. Something like this:
for (int i = 0; i < 10; i++)
Console.Write(new Random().Next(0, 9));
will often produce output like this:
5555555555
Most values in AutoFixture are generated by various Random instances - the exception is the string type, of which values are generated by Guid.NewGuid().ToString().
I think that the reason you're seeing this is because of xUnit.net's parallel execution.
In order to pinpoint the problem, I rephrased the issue so that it doesn't rely on debugging or inheritance:
public static class Reporter
{
public static void CreateValueAndReferenceType(
IFixture fixture,
ITestOutputHelper #out)
{
var valueType = fixture.Create<int>();
var referenceTye = fixture.Create<string>();
#out.WriteLine("valueType: {0}", valueType);
#out.WriteLine("referenceType: {0}", referenceTye);
}
}
public class TestClass1
{
private readonly ITestOutputHelper #out;
public TestClass1(ITestOutputHelper #out)
{
this.#out = #out;
}
[Fact]
public void Test1()
{
Reporter.CreateValueAndReferenceType(new Fixture(), this.#out);
}
}
public class TestClass2
{
private readonly ITestOutputHelper #out;
public TestClass2(ITestOutputHelper #out)
{
this.#out = #out;
}
[Fact]
public void Test2()
{
Reporter.CreateValueAndReferenceType(new Fixture(), this.#out);
}
}
When you run this with the xUnit.net console runner, you can see the issue nicely reproduced:
$ packages/xunit.runner.console.2.1.0/tools/xunit.console 37925109/bin/Debug/Ploeh.StackOverflow.Q37925109.dll -diagnostics
-parallel all
xUnit.net Console Runner (64-bit .NET 4.0.30319.42000)
Discovering: Ploeh.StackOverflow.Q37925109 (app domain = on [shadow copy], method display = ClassAndMethod)
Discovered: Ploeh.StackOverflow.Q37925109 (running 2 test cases)
Starting: Ploeh.StackOverflow.Q37925109 (parallel test collections = on, max threads = 4)
Ploeh.StackOverflow.Q37925109.TestClass2.Test2 [PASS]
Output:
valueType: 246
referenceType: cc39f570-046a-4a0a-8adf-ab7deadd0e26
Ploeh.StackOverflow.Q37925109.TestClass1.Test1 [PASS]
Output:
valueType: 246
referenceType: 87455351-03f7-4640-99fb-05af910da267
Finished: Ploeh.StackOverflow.Q37925109
=== TEST EXECUTION SUMMARY ===
Ploeh.StackOverflow.Q37925109 Total: 2, Errors: 0, Failed: 0, Skipped: 0, Time: 0,429s
In the above example, you'll notice that I've explicitly invoked the runner with -parallel all, but I didn't have to do that, since it's the default.
If, on the other hand, you turn off parallelisation with -parallel none, you'll see that the values are different:
$ packages/xunit.runner.console.2.1.0/tools/xunit.console 37925109/bin/Debug/Ploeh.StackOverflow.Q37925109.dll -diagnostics
-parallel none
xUnit.net Console Runner (64-bit .NET 4.0.30319.42000)
Discovering: Ploeh.StackOverflow.Q37925109 (app domain = on [shadow copy], method display = ClassAndMethod)
Discovered: Ploeh.StackOverflow.Q37925109 (running 2 test cases)
Starting: Ploeh.StackOverflow.Q37925109 (parallel test collections = off, max threads = 4)
Ploeh.StackOverflow.Q37925109.TestClass2.Test2 [PASS]
Output:
valueType: 203
referenceType: 1bc75a33-5542-4d9f-b42d-57ed85dc418d
Ploeh.StackOverflow.Q37925109.TestClass1.Test1 [PASS]
Output:
valueType: 117
referenceType: 6a508699-dc35-4bcd-8a7b-15eba64b24b4
Finished: Ploeh.StackOverflow.Q37925109
=== TEST EXECUTION SUMMARY ===
Ploeh.StackOverflow.Q37925109 Total: 2, Errors: 0, Failed: 0, Skipped: 0, Time: 0,348s
What I think happens is that because of the parallelism, both Test1 and Test2 are executed in parallel, and essentially within the same tick.
One workaround is to place both tests in the same test class:
public class TestClass1
{
private readonly ITestOutputHelper #out;
public TestClass1(ITestOutputHelper #out)
{
this.#out = #out;
}
[Fact]
public void Test1()
{
Reporter.CreateValueAndReferenceType(new Fixture(), this.#out);
}
[Fact]
public void Test2()
{
Reporter.CreateValueAndReferenceType(new Fixture(), this.#out);
}
}
This produces two different integer values, because (IIRC) xUnit.net only run different test classes in parallel:
$ packages/xunit.runner.console.2.1.0/tools/xunit.console 37925109/bin/Debug/Ploeh.StackOverflow.Q37925109.dll -diagnostics
-parallel all
xUnit.net Console Runner (64-bit .NET 4.0.30319.42000)
Discovering: Ploeh.StackOverflow.Q37925109 (app domain = on [shadow copy], method display = ClassAndMethod)
Discovered: Ploeh.StackOverflow.Q37925109 (running 2 test cases)
Starting: Ploeh.StackOverflow.Q37925109 (parallel test collections = on, max threads = 4)
Ploeh.StackOverflow.Q37925109.TestClass1.Test2 [PASS]
Output:
valueType: 113
referenceType: e8c30ad8-f2c8-4767-9e9f-69b55c50e659
Ploeh.StackOverflow.Q37925109.TestClass1.Test1 [PASS]
Output:
valueType: 232
referenceType: 3eb60bf3-4d43-4a91-aef2-42f7e23e35b3
Finished: Ploeh.StackOverflow.Q37925109
=== TEST EXECUTION SUMMARY ===
Ploeh.StackOverflow.Q37925109 Total: 2, Errors: 0, Failed: 0, Skipped: 0, Time: 0,360s
This theory is also corroborated by the fact that if you repeat the experiment sufficiently many times, you'll see the numbers being different once in a while. Here are the integer results from 25 test runs:
33 33
92 92
211 211
13 13
9 9
160 160
55 55
155 155
137 137
161 161
242 242
183 183
237 237
151 151
104 104
254 254
123 123
244 244
144 144
223 9
196 196
126 126
199 199
221 221
132 132
Notice that all except one test run has equal numbers.

I cannot set the AM_PM variable in Java 8 Micro Edition

I'm a teaching myself Java and am a beginner. As part of a larger project I am running code to determine, and then later set, the time on a Calendar object. I have scoured the internet for a way to set the AM_PM value but I cannot get it to work. Any suggestions would help.
package timethread;
import javax.microedition.midlet.MIDlet;
import java.util.Calendar;
/**
*
* #author Jaydawg
*/
public class TimeThread extends MIDlet {
#Override
public void startApp() {
Calendar cal = Calendar.getInstance();
System.out.println(cal.get(Calendar.AM_PM)); // Original value: it is '1' or PM
cal.add(Calendar.AM_PM, 0); // Attempt #1
System.out.println(cal.get(Calendar.AM_PM));
cal.set(Calendar.AM_PM, 0); // Attempt #2
System.out.println(cal.get(Calendar.AM_PM));
cal.set(Calendar.AM_PM, Calendar.AM); //Attempt #3
System.out.println(cal.get(Calendar.AM_PM));
cal.add(Calendar.AM_PM, Calendar.AM); //Attempt #4
System.out.println(cal.get(Calendar.AM_PM));
int min = cal.get(Calendar.MINUTE);
int sec = cal.get(Calendar.SECOND);
int hour = cal.get(Calendar.HOUR);
int AMPM = cal.get(Calendar.AM_PM);
System.out.println(AMPM);
String AMPMString = "AM";
if(cal.get(Calendar.AM_PM)==1){
AMPMString = "PM";
}
System.out.println("The time is " + hour + ":" + min + ":" + sec + " " + AMPMString);
}
My results were as follows:
1
1
1
1
1
1
The time is 1:20:42 PM
Maybe a bug with Calendar in Java 8 Micro Edition?
This works for me with Java 7:
Calendar c = Calendar.getInstance();
c.set(Calendar.AM_PM, Calendar.AM);
System.out.println(c.get(Calendar.AM_PM));
c.set(Calendar.AM_PM, Calendar.PM);
System.out.println(c.get(Calendar.AM_PM));
it outputs:
0
1
This was confirmed to be a bug by Oracle.
https://community.oracle.com/thread/3728182?sr=inbox&ru=997534

Resources