MoreRSS

site iconAnZhihe | 安志合修改

国学和传统文化爱好者,IT行业从业者,运维和SRE。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

AnZhihe | 安志合的 RSS 预览

特朗普总统就职演说(中英文)

2025-01-22 17:07:19

tlp.png

唐纳德·特朗普(Donald Trump)星期一(1月20日)宣誓就任美国第47任总统,正式开启他不连续的第二个总统任期。在就职演说中,特朗普承诺恢复“美国优先”政策,推动“常理革命”,并以“黄金时代”形容他领导下的美国未来。在长达数千字的演讲中,特朗普多次批评过去的政府政策,宣布将采取一系列行政命令,涵盖移民、能源、贸易和国家安全领域。他宣称,“美国的衰败已经结束”。

以下是根据视频整理的特朗普就职演说的全文翻译:

唐纳德·特朗普:

谢谢。非常感谢各位。非常非常感谢。万斯副总统、约翰逊议长、图恩参议员、罗伯茨首席大法官、美国最高法院大法官、克林顿总统、布什总统、奥巴马总统、拜登总统、哈里斯副总统,以及我的同胞们。美国的黄金时代现在开始了。

从今天起,我们的国家将繁荣昌盛,再次受到全世界的尊敬。我们将成为每个国家羡慕的对象,我们不会再让自己被利用了。在特朗普政府的每一天,我都会非常简单地把美国放在第一位。我们的主权将被收回。我们的安全将会恢复。正义的天平将被重新平衡。司法部和我们政府的邪恶、暴力和不公平的武器化将会结束。我们的首要任务将是建立一个自豪、繁荣和自由的国家。

美国将很快变得比以往任何时候都更伟大、更强大、更卓越。我满怀信心和乐观地重返总统宝座,相信我们正处于一个激动人心的国家成功新时代的开端,变革的浪潮正席卷全国,阳光正普照整个世界,美国有机会抓住这个前所未有的机遇。

但首先,我们必须诚实面对我们面临的挑战。虽然这些挑战众多,但他们将被全世界的目睹下被美利坚合众国这一巨大优势所消灭。

当我们今天聚集在一起的时候,我们的政府面临着信任危机。许多年来,一个激进和腐败的机构从我们的公民那里攫取权力和财富,而我们社会的支柱却断裂了,似乎完全失修。

我们现在有一个连国内简单的危机都无法管理的政府,而与此同时,在国外却陷入了一连串的灾难性事件。它未能保护我们伟大的、守法的美国公民,而是为危险的罪犯提供庇护和保护,这些罪犯中有许多来自监狱和精神病院,他们从世界各地非法进入我们的国家。

我们的政府为保卫外国边境提供了无限的资金,但却拒绝保卫美国边境,更重要的是,拒绝保卫自己的人民。我们的国家再也不能在紧急情况下提供基本服务,正如北卡罗来纳州的优秀人民最近所显示的那样,他们受到了如此恶劣的对待,和其他州仍在遭受几个月前发生的飓风一样。

或者最近在洛杉矶,我们看到几周前的大火仍在悲惨地燃烧,甚至没有一点防御的迹象。它们在房屋和社区中肆虐,甚至影响到我们国家最富有和最有权力的一些人,他们中的一些人现在就坐在这里。他们再也没有家了。很有意思,但是我们不能让这种事情再次发生。每个人对此都无能为力。这种情况将会改变。

我们的公共卫生系统在灾难发生时并没有发挥作用,但是在这方面的花费却比世界上任何一个国家都要多。我们的教育系统教导我们的孩子为自己感到羞耻,在许多情况下,尽管我们拼命地向他们提供爱,他们却仍然憎恨我们的国家。从今天开始,这一切都将改变,而且会改变得非常快。

我最近的选举被授权完全彻底地扭转一场可怕的背叛,以及所有这些已经发生的背叛,把他们的信仰、他们的财富、他们的民主,甚至他们的自由还给人民。

从这一刻起,美国的衰落结束了。我们的自由和我们国家光荣的命运将不再被否认,我们将立即恢复美国政府的诚信、能力和忠诚。在过去的八年里,我比美国250年历史上任何一位总统都经受了更多的考验和挑战,我也学到了很多。我可以告诉你,重建我们的共和国并不容易。

那些想要阻止我们事业的人试图夺走我的自由,甚至是我的生命。就在几个月前,在美丽的宾夕法尼亚州,一颗刺客的子弹穿过了我的耳朵。但我当时觉得,现在更相信,我的生命被拯救是有原因的。上帝拯救了我,让美国再次伟大。谢谢你。谢谢您们。

这就是为什么在我们美国爱国者的管理下,我们每天都将带着尊严、权力和力量努力应对每一场危机。我们将目标明确、行动迅速,为不同种族、宗教、肤色和信仰的公民带回希望、繁荣、安全与和平。对美国公民来说,2025年1月20日是解放日。

我希望我们最近的总统选举将作为我国历史上最伟大和最重要的选举而被铭记。

正如我们的胜利所表明的那样,整个国家正在迅速团结起来支持我们的议程,我们社会的几乎每一个组成部分,年轻人和老年人,男人和女人,非洲裔美国人,西班牙裔美国人,亚裔美国人,城市,郊区,农村,都给予了极大的支持。非常重要的是,我们在所有七个摇摆州都取得了巨大的胜利,我们赢得了数百万人的选票。

对于黑人和西班牙裔社区,我要感谢你们通过投票向我表达的巨大的爱和信任。我们创造了记录,我不会忘记的。我在竞选中听到了你们的声音,我期待着在未来的岁月里与你们合作。今天是马丁·路德·金日和他的荣誉,这将是一个伟大的荣誉,但为了他的荣誉,我们将共同努力,使他的梦想成为现实。我们会让他的梦想成真。谢谢你。谢谢你。

美国正在恢复国家统一,信心和自豪感空前高涨。我们做的每一件事。我的政府将受到追求卓越和不懈成功的激励。我们不会忘记我们的国家。我们不会忘记我们的宪法,也不会忘记我们的上帝。不能这么做。

今天,我将签署一系列历史性的行政命令。有了这些行动,我们将开始美国的彻底复兴和常识的革命。这一切都是常识。

首先,我将宣布我国南部边境进入全国紧急状态。所有非法入境将被立即制止,我们将开始遣返数百万犯罪的外国人回到他们来的地方。

我们将恢复我留在墨西哥的政策。我将结束抓了又放的做法。我会派军队去南部边境击退对我们国家的灾难性入侵。

根据我今天签署的命令,我们还将认定卡特尔为外国恐怖组织。通过援引1798年《外国敌人法》,我将指示我们的政府利用联邦和州执法的全部和巨大权力,消灭所有给美国国土,包括我们的城镇带来毁灭性犯罪的外国帮派和犯罪网络。作为总司令,我没有比保卫我们的国家免受威胁和入侵更高的责任,这正是我要做的。我们将会达到前所未有的水平。

下一步,我将指示我的内阁所有成员集中他们所能支配的巨大力量来战胜创纪录的通货膨胀,并迅速降低成本和价格。

通货膨胀危机是由大量超支和不断上涨的能源价格引起的,这就是为什么今天我也将宣布国家能源紧急状态。我们要开采石油,宝贝们,我们要开采石油。

美国将再次成为一个制造业国家,我们拥有其他制造业国家永远不会拥有的东西,地球上最大的石油和天然气量储藏,我们将使用它,他们也使用它。我们将降低价格,再次充实我们的战略储备,直至峰值,并将美国的能源出口到全世界。

我们将再次成为一个富裕的国家,我们脚下的液体黄金将有助于实现这一目标。

以我今天的行动,我们将结束绿色新政,我们将撤销电动汽车补贴的命令,拯救我们的汽车工业,并遵守我对我们伟大的美国汽车工人的神圣承诺。

换句话说,你可以买到自己喜欢的汽车。我们将会以几年前任何人都无法想象的速度再次在美国制造汽车,感谢你们对我们国家的汽车工人投下的鼓舞人心的信任票。我们在他们的投票中表现出色。

我将立即开始全面改革我们的贸易体系,以保护美国工人和家庭。我们不会向我们的公民征税来使其他国家富裕,而是向外国征税来使我们的公民富裕。

为此目的,我们正在建立对外税署,以征收所有关税、税款和收入。将会有来自国外的大量资金涌入我们的国库。美国梦将很快回来,并以前所未有的方式蓬勃发展。

为了恢复信心和有效地管理我们的联邦政府,我的政府将建立全新的政府效率部。

在年复一年的非法和违反宪法的限制言论自由之后,我还将签署一项行政命令,立即停止所有政府审查,将言论自由带回美国。国家的巨大权力再也不会被用来迫害政治对手。一些我知道的,一些关于我们不会允许这种情况发生。这不会再发生了。

在我的领导下,我们将在宪法法治下恢复公平、平等和公正的司法,我们将恢复我们城市的法律和秩序。

本周,我还将结束政府试图将种族和性别纳入公共和私人生活方方面面的政策。我们将打造一个不分肤色、择优录取的社会。从今天起,美国政府的官方政策将是只有两种性别,男性和女性。

本周,我将恢复所有因反对冠状病毒肺炎疫苗强制令而被不公正地开除军籍的军人的军职,并全额补发工资。我将签署一项命令,阻止我们的战士在执勤时遭受激进的政治理论和社会实验。马上就要结束了。

我们的武装部队将可以自由地专注于他们唯一的使命:击败美国的敌人。

像2017年一样,我们将再次建立世界上有史以来最强大的军队。我们将不仅以我们赢得的战斗来衡量我们的成功,而且以我们结束的战争来衡量,也许最重要的是,我们从未卷入的战争。

我最自豪的遗产将是一个和平缔造者和统一者,这就是我想成为的,一个和平缔造者和统一者。我很高兴地说,就在昨天,也就是我就职的前一天,中东的人质正在回家与家人团聚。

谢谢你。美国将重新获得其作为地球上最伟大、最强大、最受尊敬的国家的合法地位,激发整个世界的所有钦佩。

从现在起不久,我们将把墨西哥湾的名字改为美国湾,我们将把伟大的总统威廉·麦金利的名字重新命名为麦金利山,它应该在它应该在的地方。麦金利总统通过关税和人才使我们的国家变得非常富有。他是一个天生的商人,为泰迪·罗斯福做的许多伟大的事情提供资金,包括巴拿马运河,我们愚蠢地给了巴拿马这个国家,我的意思是,想想美国在巴拿马运河上比以往任何时候花在一个项目上的钱都多,在巴拿马运河的建设中失去了38,000条生命。

我们受到了这份愚蠢礼物的恶劣对待,巴拿马违背了对我们的承诺。我们交易的目的和我们条约的精神被完全违背了。美国船只正被严重超额收费、收费,并且在任何方面、任何形式上都没有得到公平对待。这包括美国海军,最重要的是,~国正在运营巴拿马运河,我们没有把它给~国,我们把它给了巴拿马,我们要收回它。

最重要的是,今天我要向美国人民传达的信息是,我们是时候再次以历史上最伟大文明的勇气、活力和生机采取行动了。因此,当我们解放我们的国家时,我们将带领它走向胜利和成功的新高度。我们不会被吓倒。

我们将携手终结慢性病流行,让我们的孩子安全、健康、远离疾病。美国将再次认为自己是一个不断成长的国家,一个增加我们的财富、扩大我们的领土、建设我们的城市、提高我们的期望、把我们的旗帜带入新的美丽的地平线的国家。

我们将追求我们的天定命运。我们要发射美国宇航员在火星上插上星条旗。

雄心是一个伟大国家的命脉,现在,我们的国家比任何其他国家都更有雄心。没有一个国家像我们的国家一样。美国人是探险者、建设者、创新者、企业家和开拓者。边疆精神写在我们心里。下一次伟大冒险的召唤在我们的灵魂深处回响。

我们的美洲祖先把一个大洲边缘的一小群殖民地变成了一个由地球上最非凡的公民组成的强大的共和国。没人能接近。美国人穿越了数千英里崎岖不平的蛮荒之地。

他们穿越沙漠,攀登高山,勇敢地面对无数的危险,赢得了西部大开发,结束了奴隶制,从暴政中拯救了数百万人,使数十亿人摆脱了贫困,利用电力,分裂了原子,将人类送上了太空,并将人类知识的宇宙置于人类的手掌之中。

如果我们一起努力,就没有我们做不到的事,没有我们实现不了的梦想。许多人认为我不可能上演这样一场历史性的政治复出。但是正如你今天看到的,我在这里,美国人民已经话事了。我现在站在你们面前证明了你们永远不应该相信有些事情是不可能做到的。

在美国,所谓不可能的事情却是我们最擅长的。从纽约到洛杉矶,从费城到凤凰城,从芝加哥到迈阿密,从休斯顿到华盛顿,我们的国家是由一代又一代的爱国者缔造和建设的,他们为我们的权利和自由献出了一切。他们是农民和士兵,牛仔和工厂工人,钢铁工人和煤矿工人,警察和先锋,他们勇往直前,勇往直前,不让任何障碍摧毁他们的精神和骄傲。

他们一起铺设铁路,建造摩天大楼,修建高速公路,赢得了两次世界大战,打败了法西斯主义,战胜了他们面临的每一个挑战。在我们一起经历了这么多之后,我们即将迎来美国历史上最伟大的四年。在你们的帮助下,我们将重塑美国的承诺,我们将重建我们热爱的国家。

我们是一个民族,一个家庭,上帝庇佑下的一个光荣的国家。所以,对每一个为自己的孩子梦想的父母和每一个为自己的未来梦想的孩子,我与你们同在。我会为你而战,为你而赢。我们将赢得前所未有的胜利。谢谢你。谢谢你。谢谢你。谢谢你。

近年来,我们的国家遭受了巨大的痛苦,但我们将把它带回来,使它再次伟大,比以往任何时候都更伟大。我们将是一个与众不同的国家,充满同情、勇气和独特性。我们的力量将停止所有的战争,给这个充满愤怒、暴力和完全不可预测的世界带来新的团结精神。

美国将再次受到尊重和钦佩,包括宗教、信仰和善意的人们。我们将会繁荣昌盛。我们会骄傲的。我们会变得强大,我们会赢得前所未有的胜利。我们不会被征服。我们不会被吓倒。我们不会被击垮,也不会失败。

从今天起,美利坚合众国将成为一个自由、主权和独立的国家。我们将勇敢地站出来。我们将自豪地生活。我们将大胆梦想,没有什么会阻挡我们,因为我们是美国人。

未来是我们的,我们的黄金时代才刚刚开始。谢谢你。

上帝保佑美国。

谢谢大家。谢谢你。谢谢你们。


The full text of Trump's inauguration speech

Vice President Vance, Speaker Johnson, Senator Thune, Chief Justice Roberts, justices of the United States Supreme Court, President Clinton, President Bush, President Obama, President Biden, Vice President Harris and my fellow citizens:

The golden age of America begins right now. From this day forward, our country will flourish and be respected again all over the world. We will be the envy of every nation. And we will not allow ourselves to be taken advantage of any longer.

During every single day of the Trump administration, I will, very simply, put America first. Our sovereignty will be reclaimed. Our safety will be restored. The scales of justice will be rebalanced. The vicious, violent and unfair weaponization of the Justice Department and our government will end. And our top priority will be to create a nation that is proud and prosperous and free.

America will soon be greater, stronger, and far more exceptional than ever before. I return to the presidency confident and optimistic that we are at the start of a thrilling new era of national success. A tide of change is sweeping the country. Sunlight is pouring over the entire world, and America has the chance to seize this opportunity like never before.

But first, we must be honest about the challenges we face. While they are plentiful, they will be annihilated by this great momentum that the world is now witnessing and the United States of America. As we gather today, our government confronts a crisis of trust. For many years, the radical and corrupt establishment has extracted power and wealth from our citizens. While the pillars of our society lay broken and seemingly in complete disrepair, we now have a government that cannot manage even a simple crisis at home while at the same time stumbling into a continuing catalog of catastrophic events abroad.

It fails to protect our magnificent, law-abiding American citizens but provides sanctuary and protection for dangerous criminals, many from prisons and mental institutions that have illegally entered our country from all over the world. We have a government that has given unlimited funding to the defense of foreign borders but refuses to defend American borders, or more importantly, its own people.

Our country can no longer deliver basic services in times of emergency, as recently shown by the wonderful people of North Carolina, who've been treated so badly. And other states who are still suffering from a hurricane that took place many months ago. Or more recently, Los Angeles, where we are watching fires still tragically burn from weeks ago without even a token of defense. They're raging through the houses and communities, even affecting some of the wealthiest and most powerful individuals in our country, some of whom are sitting here right now. They don't have a home any longer. That's interesting.

But we can't let this happen. Everyone is unable to do anything about it. That's going to change. We have a public health system that does not deliver in times of disaster, yet more money is spent on it than any country anywhere in the world. And we have an education system that teaches our children to be ashamed of themselves, in many cases to hate our country despite the love that we try so desperately to provide to them. All of this will change starting today and will change very quickly.

Our recent election is a mandate to completely and totally reverse a horrible betrayal, and all of these many betrayals that have taken place, and to give the people back their faith, their wealth, their democracy and indeed their freedom. From this moment on, America's decline is over.

Our liberties and our nation's glorious destiny will no longer be denied and we will immediately restore the integrity, competency and loyalty of America's government. Over the past eight years, I have been tested and challenged more than any president in our 250-year history, and I've learned a lot along the way. The journey to reclaim our Republic has not been an easy one, that I can tell you. Those who wish to stop our cause have tried to take my freedom and indeed to take my life. Just a few months ago, in a beautiful Pennsylvania field, an assassin's bullet ripped through my ear. But I felt then, and believe even more so now, that my life was saved for a reason. I was saved by God to make America great again.

That is why each day under our administration of American patriots, we will be working to meet every crisis with dignity and power and strength. We will move with purpose and speed to bring back hope, prosperity, safety and peace for citizens of every race, religion, color and creed. For American citizens, Jan. 20, 2025, is Liberation Day.

It is my hope that our recent presidential election will be remembered as the greatest and most consequential election in the history of our country. As our victory showed, the entire nation is rapidly unifying behind our agenda with dramatic increases in support from virtually every element of our society. Young and old, men and women, African Americans, Hispanic Americans, Asian Americans, urban, suburban and rural. And, very importantly, we had a powerful win in all seven swing states and the popular vote. We won by millions of people.

To the Black and Hispanic communities, I want to thank you for the tremendous outpouring of love and trust that you have shown me with your vote. We set records, and I will not forget it. I've heard your voices in the campaign, and I look forward to working with you in the years to come.

Today is Martin Luther King Day and his honor — this will be a great honor — but in his honor, we will strive together to make his dream a reality. We will make his dream come true.

National unity is now returning to America and confidence and pride is soaring like never before. In everything we do my administration will be inspired by a strong pursuit of excellence and unrelenting success. We will not forget our country. We will not forget our Constitution. And we will not forget our God.

Today, I will sign a series of historic executive orders. With these actions, we will begin the complete restoration of America and the revolution of common sense. It's all about common sense. 

First, I will declare a national emergency at our southern border. All illegal entry will immediately be halted. And we will begin the process of returning millions and millions of criminal aliens back to the places from which they came. We will reinstate my remain in Mexico policy. I will end the practice of catch and release. And I will send troops to the southern border to repel the disastrous invasion of our country. 

Under the orders I sign today we will also be designating the cartels as foreign terrorist organizations. And by invoking the Alien Enemies Act of 1798, I will direct our government to use the full and immense power of federal and state law enforcement to eliminate the presence of all foreign gangs and criminal networks bringing devastating crime to U.S. soil, including our cities and inner cities.

As commander in chief, I have no higher responsibility than to defend our country from threats and invasions. And that is exactly what I am going to do. We will do it at a level that nobody has ever seen before. Next, I will direct all members of my cabinet to marshal the vast powers at their disposal to defeat what was record inflation and rapidly bring down costs and prices. The inflation crisis was caused by massive overspending and escalating energy prices. And that is why today I will also declare a national energy emergency. We will drill, baby, drill.

America will be a manufacturing nation once again, and we have something that no other manufacturing nation will ever have: the largest amount of oil and gas of any country on Earth. And we are going to use it. We will bring prices down, fill our strategic reserves up again, right to the top, and export American energy all over the world. We will be a rich nation again. And it is that liquid gold under our feet that will help to do it.

With my actions today, we will end the Green New Deal and we will revoke the electric vehicle mandate, saving our auto industry and keeping my sacred pledge to our great American autoworkers. In other words, you'll be able to buy the car of your choice. We will build automobiles in America again at a rate that nobody could have dreamt possible just a few years ago. And thank you to the auto workers of our nation for your inspiring vote of confidence. We did tremendously with their vote.

I will immediately begin the overhaul of our trade system to protect American workers and families. Instead of taxing our citizens to enrich other countries, we will tariff and tax foreign countries to enrich our citizens. For this purpose, we are establishing the External Revenue Service to collect all tariffs, duties and revenues. It will be massive amounts of money pouring into our treasury coming from foreign sources.

The American Dream will soon be back and thriving like never before. To restore confidence and effectiveness to our federal government, my administration will establish the brand new Department of Government Efficiency.

After years and years of illegal and unconstitutional federal efforts to restrict free expression, I will also sign an executive order to immediately stop all government censorship and bring back free speech to America. Never again will the immense power of the state be weaponized to persecute political opponents. Something I know something about. We will not allow that to happen. It will not happen again. Under my leadership, we will restore fair, equal and impartial justice under the Constitution and the rule of law. And we are going to bring law and order back to our cities.

This week, I will also end the government policy of trying to socially engineer race and gender into every aspect of public and private life. We will forge a society that is colorblind and merit based. As of today, it will henceforth be the official policy of the United States government that there are only two genders, male and female. This week I will reinstate any service members who were unjustly expelled from the military for objecting to the Covid vaccine mandate with full back pay. And I will sign an order to stop our warriors from being subjected to radical political theories and social experiments while on duty. It's going to end immediately. Our armed forces will be free to focus on their sole mission—defeating America's enemies. Like in 2017, we will again build the strongest military the world has ever seen.

We will measure our success not only by the battles we win but also by the wars that we end. And, perhaps most importantly, the wars we never get into. My proudest legacy will be that of a peacemaker and unifier. That's what I want to be. A peacemaker and a unifier. I'm pleased to say that, as of yesterday, one day before I assumed office, the hostages in the Middle East are coming back home to their families.

America will reclaim its rightful place as the greatest, most powerful, most respected nation on earth, inspiring the awe and admiration of the entire world. A short time from now, we are going to be changing the name of the Gulf of Mexico to the Gulf of America. And we will restore the name of the great President William McKinley to Mount McKinley, where it should be and where it belongs. President McKinley made our country very rich through tariffs and through talent.

He was a natural businessman and gave Teddy Roosevelt the money for many of the great things he did, including the Panama Canal, which has foolishly been given to the country of Panama after the United States — the United States, I mean, think of this, spent more money than ever spent on a project before and lost 38,000 lives in the building of the Panama Canal. We have been treated very badly from this foolish gift that should have never been made. And Panama's promise to us has been broken. 

The purpose of our deal and the spirit of our treaty has been totally violated. American ships are being severely overcharged and not treated fairly in any way, shape or form, and that includes the United States Navy. And above all, China is operating the Panama Canal. And we didn't give it to China, we gave it to Panama, and we're taking it back.

Above all, my message to Americans today is that it is time for us to once again act with courage, vigor and the vitality of history's greatest civilization. So as we liberate our nation, we will lead it to new heights of victory and success. We will not be deterred. Together, we will end the chronic disease epidemic and keep our children safe, healthy and disease free. 

The United States will once again consider itself a growing nation, one that increases our wealth, expands our territory, builds our cities, raises our expectations and carries our flag into new and beautiful horizons. And we will pursue our manifest destiny into the stars, launching American astronauts to plant the Stars and Stripes on the planet Mars.

And it's the lifeblood of a great nation. And, right now, our nation is more ambitious than any other. There's no nation like our nation. Americans are explorers, builders, innovators, entrepreneurs and pioneers. The spirit of the frontier is written into our hearts. The call of the next great adventure resounds from within our souls. Our American ancestors turned a small group of colonies on the edge of a vast continent into a mighty republic of the most extraordinary citizens on Earth. No one comes close. 

Americans pushed thousands of miles through a rugged land of untamed wilderness. They crossed deserts, scaled mountains, braved untold dangers, won the Wild West, ended slavery, rescued millions from tyranny, lifted millions from poverty, harnessed electricity, split the atom, launched mankind into the heavens and put the universe of human knowledge into the palm of the human hand. If we work together, there is nothing we cannot do and no dream we cannot achieve.

Many people thought it was impossible for me to stage such a historic political comeback. But as you see today, here I am. The American people have spoken. I stand before you now as proof that you should never believe that something is impossible to do. 

In America, the impossible is what we do best. From New York to Los Angeles, from Philadelphia to Phoenix, from Chicago to Miami, from Houston to right here in Washington, D.C., our country was forged and built by the generations of patriots who gave everything they had for our rights and for our freedom. They were farmers and soldiers, cowboys and factory workers, steel workers and coal miners, police officers and pioneers who pushed onward, marched forward and let no obstacle defeat their spirit or their pride. Together they laid down the railroads, raised up the skyscrapers, built great highways, won two world wars, defeated fascism and communism, and triumphed over every single challenge that they faced.

After all we have been through together, we stand on the verge of the four greatest years in American history. With your help, we will restore an American promise and we will rebuild the nation that we love. And we love it so much. We are one people, one family and one glorious nation under God. So to every parent who dreams for their child and every child to dreams for their future: I am with you, I will fight for you and I will win for you. And we're going to win like never before.

In recent years, our nation has suffered greatly. But we are going to bring it back and make it great again. Greater than ever before. We will be a nation like no other. Full of compassion, courage and exceptionalism. Our power will stop all wars and bring a new spirit of unity to a world that has been angry, violent, and totally unpredictable.

America will be respected again and admired again, including by people of religion, faith and goodwill. We will be prosperous. We will be proud. We will be strong and we will win like never before. We will not be conquered. We will not be intimidated. We will not be broken. And we will not fail.

From this day on, the United States of America will be a free, sovereign and independent nation. We will stand bravely. We will live proudly. We will dream boldly, and nothing will stand in our way. Because we are Americans. The future is ours. And our golden age has just begun.

Thank you. God bless America. Thank you all. Thank you.


参考:2021.1.19日 川普告別演說(中英双语)


JVM Serial GC 、Parallel GC 日志解读与分析

2025-01-20 10:45:00

上一节 JVM GC 日志解读与分析(基础配置)讲述了 GC 日志相关的基础信息和配置。需要提醒的是,这些参数是基于 JDK 8 配置的。

在 JDK 9 之后的版本中,启动参数有一些变化,继续使用原来的参数配置可能会在启动时报错。不过也不用担心,如果碰到,一般都可以从错误提示中找到对应的处置措施和解决方案。

例如 JDK 11 版本中打印 info 级别 GC 日志的启动脚本:

# JDK 11 环境,输出 info 级别的 GC 日志
java -Xms512m -Xmx512m
-Xlog:gc*=info:file=gc.log:time:filecount=0
demo.jvm0204.GCLogAnalysis

从 JDK 9 开始,可以使用命令 java -Xlog:help 来查看当前 JVM 支持的日志参数,本文不进行详细的介绍,有兴趣的同学可以查看 JEP 158: Unified JVM Logging 和 JEP 271: Unified GC Logging

另外,JMX 技术提供了 GC 事件的通知机制,监听 GC 事件的示例程序我们会在《应对容器时代面临的挑战》这一章节中给出。

但很多情况下 JMX 通知事件中报告的 GC 数据并不完全,只是一个粗略的统计汇总。

GC 日志才是我们了解 JVM 和垃圾收集器最可靠和全面的信息,因为里面包含了很多细节。再次强调,分析 GC 日志是一项很有价值的技能,能帮助我们更好地排查性能问题。

下面我们通过实际操作来分析和解读 GC 日志。

Serial GC 日志解读

关于串行垃圾收集器的介绍,请参考前面的文章:《常见 GC 算法介绍》。

首先,为了打开 GC 日志记录,我们使用下面的 JVM 启动参数如下:

# 请注意命令行启动时没有换行,此处是手工排版
java -XX:+UseSerialGC
-Xms512m -Xmx512m
-Xloggc:gc.demo.log
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
demo.jvm0204.GCLogAnalysis

让我们看看 Serial GC 的垃圾收集日志,并从中提取信息。

启用串行垃圾收集器,程序执行后输出的 GC 日志类似这样(为了方便大家阅读,已手工折行):

Java HotSpot(TM) 64-Bit Server VM (25.162-b12) ......
Memory: 4k page,physical 16777216k(1551624k free)
CommandLine flags:
  -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=536870912
  -XX:+PrintGC -XX:+PrintGCDateStamps
  -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
  -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
  -XX:+UseSerialGC
2019-12-15T15:18:36.592-0800: 0.420:
  [GC (Allocation Failure)
    2019-12-15T15:18:36.592-0800: 0.420:
    [DefNew: 139776K->17472K(157248K),0.0364555 secs]
    139776K->47032K(506816K),
    0.0365665 secs]
  [Times: user=0.02 sys=0.01,real=0.03 secs]
......
2019-12-15T15:18:37.081-0800: 0.908:
  [GC (Allocation Failure)
    2019-12-15T15:18:37.081-0800: 0.908:
    [DefNew: 156152K->156152K(157248K),0.0000331 secs]
    2019-12-15T15:18:37.081-0800: 0.908:
    [Tenured: 299394K->225431K(349568K),0.0539242 secs]
    455546K->225431K(506816K),
    [Metaspace: 3431K->3431K(1056768K)],
    0.0540948 secs]
  [Times: user=0.05 sys=0.00,real=0.05 secs]

日志的第一行是 JVM 版本信息,第二行往后到第一个时间戳之间的部分,展示了内存分页、物理内存大小,命令行参数等信息,这部分前面介绍过,不在累述。

仔细观察,我们发现在这段日志中发生了两次 GC 事件,其中一次清理的是年轻代,另一次清理的是整个堆内存。让我们先来分析前一次年轻代 GC 事件。

Minor GC 日志分析

这次年轻代 GC 事件对应的日志内容:

2019-12-15T15:18:36.592-0800: 0.420:
  [GC (Allocation Failure)
    2019-12-15T15:18:36.592-0800: 0.420:
    [DefNew: 139776K->17472K(157248K),0.0364555 secs]
    139776K->47032K(506816K),
    0.0365665 secs]
  [Times: user=0.02 sys=0.01,real=0.03 secs]

从中可以解读出这些信息:

  1. 2019-12-15T15:18:36.592-0800:GC 事件开始的时间点。其中 -0800 表示当前时区为东八区,这只是一个标识,方便我们直观判断 GC 发生的时间点。后面的 0.420 是 GC 事件相对于 JVM 启动时间的间隔,单位是秒。

  2. GC 用来区分 Minor GC 还是 Full GC 的标志。GC 表明这是一次小型 GC(Minor GC),即年轻代 GC。Allocation Failure 表示触发 GC 的原因。本次 GC 事件,是由于对象分配失败,年轻代中没有空间来存放新生成的对象引起的。

  3. DefNew 表示垃圾收集器的名称。这个名字表示:年轻代使用的单线程、标记—复制、STW 垃圾收集器。139776K->17472K 表示在垃圾收集之前和之后的年轻代使用量。(157248K) 表示年轻代的总空间大小。进一步分析可知:GC 之后年轻代使用率为 11%。

  4. 139776K->47032K(506816K) 表示在垃圾收集之前和之后整个堆内存的使用情况。(506816K) 则表示堆内存可用的总空间大小。进一步分析可知:GC 之后堆内存使用量为 9%。

  5. 0.0365665 secs:GC 事件持续的时间,以秒为单位。

  6. [Times: user=0.02 sys=0.01,real=0.03 secs]:此次 GC 事件的持续时间,通过三个部分来衡量。user 部分表示所有 GC 线程消耗的 CPU 时间;sys 部分表示系统调用和系统等待事件消耗的时间。real 则表示应用程序暂停的时间。因为串行垃圾收集器(Serial Garbage Collector)只使用单个线程,所以这里 real=user+system,0.03 秒也就是 30 毫秒。

凭经验,这个暂停时间对大部分系统来说可以接受,但对某些延迟敏感的系统就不太理想了,比如实时的游戏服务、高频交易业务,30ms 暂停导致的延迟可能会要了亲命。

这样解读之后,我们可以分析 JVM 在 GC 事件中的内存使用以及变化情况。

在此次垃圾收集之前,堆内存总的使用量为 139776K,其中年轻代使用了 139776K。可以算出,GC 之前老年代空间的使用量为 0。(实际上这是 GC 日志中的第一条记录)

这些数字中蕴含了更重要的信息:

  • GC 前后对比,年轻代的使用量为 139776K->17472K,减少了 122304K。

  • 但堆内存的总使用量 139776K->47032K,只下降了 92744K。

可以算出,从年轻代提升到老年代的对象占用了“122304K-92744K=29560K”的内存空间。当然,另一组数字也能推算出 GC 之后老年代的使用量:47032K-17472K=29560K。

总结:

通过这么分析下来,同学们应该发现,我们关注的主要是两个数据:GC 暂停时间,以及 GC 之后的内存使用量/使用率。

此次 GC 事件的示意图如下所示:

mgc.png

Full GC 日志分析

分析完第一次 GC 事件之后,我们心中应该有个大体的模式了。一起来看看另一次 GC 事件的日志:

2019-12-15T15:18:37.081-0800: 0.908:
  [GC (Allocation Failure)
    2019-12-15T15:18:37.081-0800: 0.908:
    [DefNew: 156152K->156152K(157248K),0.0000331 secs]
    2019-12-15T15:18:37.081-0800: 0.908:
    [Tenured: 299394K->225431K(349568K),0.0539242 secs]
    455546K->225431K(506816K),
    [Metaspace: 3431K->3431K(1056768K)],
    0.0540948 secs]
  [Times: user=0.05 sys=0.00,real=0.05 secs]

从中可以解读出这些信息:

  1. 2019-12-15T15:18:37.081-0800:GC 事件开始的时间。

  2. [DefNew: 156152K->156152K(157248K),0.0000331 secs]:前面已经解读过了,因为内存分配失败,发生了一次年轻代 GC。此次 GC 同样用的 DefNew 收集器。注意:此次垃圾收集消耗了 0.0000331 秒,基本上确认本次 GC 事件没怎么处理年轻代。

  3. Tenured:用于清理老年代空间的垃圾收集器名称。Tenured 表明使用的是单线程的 STW 垃圾收集器,使用的算法为“标记—清除—整理(mark-sweep-compact)”。 299394K->225431K(349568K) 表示 GC 前后老年代的使用量,以及老年代的空间大小。0.0539242 secs 是清理老年代所花的时间。

  4. 455546K->225431K(506816K):在 GC 前后整个堆内存部分的使用情况,以及可用的堆空间大小。

  5. [Metaspace: 3431K->3431K(1056768K)]:Metaspace 空间的变化情况。可以看出,此次 GC 过程中 Metaspace 也没有什么变化。

  6. [Times: user=0.05 sys=0.00,real=0.05 secs]:GC 事件的持续时间,分为 user、sys、real 三个部分。因为串行垃圾收集器只使用单个线程,因此“real=user+system”。50 毫秒的暂停时间,比起前面年轻代的 GC 来说增加了一倍左右。这个时间跟什么有关系呢?答案是:GC 时间,与 GC 后存活对象的总数量关系最大。

进一步分析这些数据,GC 之后老年代的使用率为:225431K/349568K=64%,这个比例不算小,但也不能就此说出了什么问题,毕竟 GC 后内存使用量下降了,还需要后续的观察……

和年轻代 GC 相比,比较明显的差别是此次 GC 事件清理了老年代和 Metaspace。

总结:

FullGC,我们主要关注 GC 之后内存使用量是否下降,其次关注暂停时间。简单估算,GC 后老年代使用量为 220MB 左右,耗时 50ms。如果内存扩大 10 倍,GC 后老年代内存使用量也扩大 10 倍,那耗时可能就是 500ms 甚至更高,就会系统有很明显的影响了。这也是我们说串行 GC 性能弱的一个原因,服务端一般是不会采用串行 GC 的。

此次 GC 事件的内存变化情况,可以表示为下面的示意图:

fgc.png

年轻代看起来数据几乎没变化,怎么办?因为上下文其实还有其他的 GC 日志记录,我们照着这个格式去解读即可。

Parallel GC 日志解读

并行垃圾收集器对年轻代使用“标记—复制(mark-copy)”算法,对老年代使用“标记—清除—整理(mark-sweep-compact)”算法。

年轻代和老年代的垃圾回收时都会触发 STW 事件,暂停所有的应用线程,再来执行垃圾收集。在执行“标记”和“复制/整理”阶段时都使用多个线程,因此得名“Parallel”。

通过多个 GC 线程并行执行的方式,能使 JVM 在多 CPU 平台上的 GC 时间大幅减少。

通过命令行参数 -XX:ParallelGCThreads=NNN 可以指定 GC 线程的数量,其默认值为 CPU 内核数量。

下面的三组命令行参数是等价的,都可用来指定并行垃圾收集器:

-XX:+UseParallelGC
-XX:+UseParallelOldGC
-XX:+UseParallelGC -XX:+UseParallelOldGC

示例:

# 请注意命令行启动时没有换行
java -XX:+UseParallelGC
-Xms512m -Xmx512m
-Xloggc:gc.demo.log
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
demo.jvm0204.GCLogAnalysis

并行垃圾收集器适用于多核服务器,其主要目标是增加系统吞吐量(也就是降低 GC 总体消耗的时间)。为了达成这个目标,会使用尽可能多的 CPU 资源:

  • 在 GC 事件执行期间,所有 CPU 内核都在并行地清理垃圾,所以暂停时间相对来说更短;

  • 在两次 GC 事件中间的间隔期,不会启动 GC 线程,所以这段时间内不会消耗任何系统资源。

另一方面,因为并行 GC 的所有阶段都不能中断,所以并行 GC 很可能会出现长时间的卡顿。

长时间卡顿的意思,就是并行 GC 启动后,一次性完成所有的 GC 操作,所以单次暂停的时间较长。

假如系统延迟是非常重要的性能指标,那么就应该选择其他垃圾收集器。

执行上面的命令行,让我们看看并行垃圾收集器的 GC 日志长什么样子:

CommandLine flags:
-XX:InitialHeapSize=536870912 -XX:MaxHeapSize=536870912
-XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
-XX:+UseCompressedClassPointers -XX:+UseCompressedOops
-XX:+UseParallelGC
......
2019-12-18T00:37:47.463-0800: 0.690:
  [GC (Allocation Failure)
    [PSYoungGen: 104179K->14341K(116736K)]
    383933K->341556K(466432K),0.0229343 secs]
  [Times: user=0.04 sys=0.08,real=0.02 secs]
2019-12-18T00:37:47.486-0800: 0.713:
  [Full GC (Ergonomics)
    [PSYoungGen: 14341K->0K(116736K)]
    [ParOldGen: 327214K->242340K(349696K)]
    341556K->242340K(466432K),
    [Metaspace: 3322K->3322K(1056768K)],
  0.0656553 secs]
  [Times: user=0.30 sys=0.02,real=0.07 secs]
......

如果跑出来的 GC 日志和阶段不一样的话,可以多跑几次试试,因为我们用了随机数嘛。

Minor GC 日志分析

前面的 GC 事件是发生在年轻代 Minor GC:

2019-12-18T00:37:47.463-0800: 0.690:
  [GC (Allocation Failure)
    [PSYoungGen: 104179K->14341K(116736K)]
    383933K->341556K(466432K),0.0229343 secs]
  [Times: user=0.04 sys=0.08,real=0.02 secs]

解读如下:

  1. 2019-12-18T00:37:47.463-0800: 0.690:GC 事件开始的时间。

  2. GC:用来区分 Minor GC 还是 Full GC 的标志。这里是一次“小型 GC(Minor GC)”。

  3. PSYoungGen:垃圾收集器的名称。这个名字表示的是在年轻代中使用并行的“标记—复制(mark-copy)”,全线暂停(STW)垃圾收集器。104179K->14341K(116736K) 表示 GC 前后的年轻代使用量,以及年轻代的总大小,简单计算 GC 后的年轻代使用率 14341K/116736K=12%。

  4. 383933K->341556K(466432K) 则是 GC 前后整个堆内存的使用量,以及此时可用堆的总大小,GC 后堆内存使用率为 341556K/466432K=73%,这个比例不低,事实上前面已经发生过 FullGC 了,只是这里没有列出来。

  5. [Times: user=0.04 sys=0.08,real=0.02 secs]:GC 事件的持续时间,通过三个部分来衡量。user 表示 GC 线程所消耗的总 CPU 时间,sys 表示操作系统调用和系统等待事件所消耗的时间; real 则表示应用程序实际暂停的时间。因为并不是所有的操作过程都能全部并行,所以在 Parallel GC 中,real 约等于 user+system/GC 线程数。笔者的机器是 8 个物理线程,所以默认是 8 个 GC 线程。分析这个时间,可以发现,如果使用串行 GC,可能得暂停 120 毫秒,但并行 GC 只暂停了 20 毫秒,实际上性能是大幅度提升了。

通过这部分日志可以简单算出:在 GC 之前,堆内存总使用量为 383933K,其中年轻代为 104179K,那么可以算出老年代使用量为 279754K。

在此次 GC 完成后,年轻代使用量减少了 104179K-14341K=89838K,总的堆内存使用量减少了 383933K-341556K=42377K。

那么我们可以计算出有“89838K-42377K=47461K”的对象从年轻代提升到老年代。老年代的使用量为:341556K-14341K=327215K。

老年代的大小为 466432K-116736K=349696K,使用率为 327215K/349696K=93%,基本上快满了。

总结:

年轻代 GC,我们可以关注暂停时间,以及 GC 后的内存使用率是否正常,但不用特别关注 GC 前的使用量,而且只要业务在运行,年轻代的对象分配就少不了,回收量也就不会少。

此次 GC 的内存变化示意图为:

pgc.png

Full GC 日志分析

前面介绍了并行 GC 清理年轻代的 GC 日志,下面来看看清理整个堆内存的 GC 日志:

2019-12-18T00:37:47.486-0800: 0.713:
  [Full GC (Ergonomics)
    [PSYoungGen: 14341K->0K(116736K)]
    [ParOldGen: 327214K->242340K(349696K)]
    341556K->242340K(466432K),
    [Metaspace: 3322K->3322K(1056768K)],
  0.0656553 secs]
  [Times: user=0.30 sys=0.02,real=0.07 secs]

解读一下:

  1. 2019-12-18T00:37:47.486-0800:GC 事件开始的时间。

  2. Full GC:完全 GC 的标志。Full GC 表明本次 GC 清理年轻代和老年代,Ergonomics 是触发 GC 的原因,表示 JVM 内部环境认为此时可以进行一次垃圾收集。

  3. [PSYoungGen: 14341K->0K(116736K)]:和上面的示例一样,清理年轻代的垃圾收集器是名为“PSYoungGen”的 STW 收集器,采用“标记—复制(mark-copy)”算法。年轻代使用量从 14341K 变为 0,一般 Full GC 中年轻代的结果都是这样。

  4. ParOldGen:用于清理老年代空间的垃圾收集器类型。在这里使用的是名为 ParOldGen 的垃圾收集器,这是一款并行 STW 垃圾收集器,算法为“标记—清除—整理(mark-sweep-compact)”。327214K->242340K(349696K)]:在 GC 前后老年代内存的使用情况以及老年代空间大小。简单计算一下,GC 之前,老年代使用率为 327214K/349696K=93%,GC 后老年代使用率 242340K/349696K=69%,确实回收了不少。那么有多少内存提升到老年代呢?其实在 Full GC 里面不好算,而在 Minor GC 之中比较好算,原因大家自己想一想。

  5. 341556K->242340K(466432K):在垃圾收集之前和之后堆内存的使用情况,以及可用堆内存的总容量。简单分析可知,GC 之前堆内存使用率为 341556K/466432K=73%,GC 之后堆内存的使用率为:242340K/466432K=52%。

  6. [Metaspace: 3322K->3322K(1056768K)]:前面我们也看到了关于 Metaspace 空间的类似信息。可以看出,在 GC 事件中 Metaspace 里面没有回收任何对象。

  7. 0.0656553secs:GC 事件持续的时间,以秒为单位。

  8. [Times: user=0.30 sys=0.02,real=0.07 secs]:GC 事件的持续时间,含义参见前面。

Full GC 和 Minor GC 的区别是很明显的,此次 GC 事件除了处理年轻代,还清理了老年代和 Metaspace。

总结:

Full GC 时我们更关注老年代的使用量有没有下降,以及下降了多少。如果 FullGC 之后内存不怎么下降,使用率还很高,那就说明系统有问题了。

此次 GC 的内存变化示意图为:

pfgc.png

细心的同学可能会发现,此次 FullGC 事件和前一次 MinorGC 事件是紧挨着的:0.690+0.02secs~0.713。因为 Minor GC 之后老年代使用量达到了 93%,所以接着就触发了 Full GC。

来源:《JVM 核心技术 32 讲》

JVM GC 日志解读与分析(基础配置)

2025-01-16 15:43:03

通过具体示例来演示如何输出 GC 日志,并对输出的日志信息进行解读分析,从中提取有用的信息。

本次演示的示例代码

为了演示需要,我们先来编写一段简单的 Java 代码:

package demo.jvm0204;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
/*
演示 GC 日志生成与解读
*/
public class GCLogAnalysis {
    private static Random random = new Random();
    public static void main(String[] args) {
        // 当前毫秒时间戳
        long startMillis = System.currentTimeMillis();
        // 持续运行毫秒数; 可根据需要进行修改
        long timeoutMillis = TimeUnit.SECONDS.toMillis(1);
        // 结束时间戳
        long endMillis = startMillis + timeoutMillis;
        LongAdder counter = new LongAdder();
        System.out.println("正在执行...");
        // 缓存一部分对象; 进入老年代
        int cacheSize = 2000;
        Object[] cachedGarbage = new Object[cacheSize];
        // 在此时间范围内,持续循环
        while (System.currentTimeMillis() < endMillis) {
            // 生成垃圾对象
            Object garbage = generateGarbage(100*1024);
            counter.increment();
            int randomIndex = random.nextInt(2 * cacheSize);
            if (randomIndex < cacheSize) {
                cachedGarbage[randomIndex] = garbage;
            }
        }
        System.out.println("执行结束!共生成对象次数:" + counter.longValue());
    }

    // 生成对象
    private static Object generateGarbage(int max) {
        int randomSize = random.nextInt(max);
        int type = randomSize % 4;
        Object result = null;
        switch (type) {
            case 0:
                result = new int[randomSize];
                break;
            case 1:
                result = new byte[randomSize];
                break;
            case 2:
                result = new double[randomSize];
                break;
            default:
                StringBuilder builder = new StringBuilder();
                String randomString = "randomString-Anything";
                while (builder.length() < randomSize) {
                    builder.append(randomString);
                    builder.append(max);
                    builder.append(randomSize);
                }
                result = builder.toString();
                break;
        }
        return result;
    }
}

程序并不复杂,我们指定一个运行时间作为退出条件,时间一到自动退出循环。在 generateGarbage 方法中,我们用了随机数来生成各种类型的数组对象并返回。

在 main 方法中,我们用一个数组来随机存放一部分生成的对象,这样可以模拟让部分对象晋升到老年代。具体的持续运行时间和缓存对象个数,各位同学可以自己进行调整。

一般来说,Java 中的大对象主要就是各种各样的数组,比如开发中最常见的字符串,实际上 String 内部就是使用字符数组 char[] 来存储的。

额外说一句,这个示例除了可以用来进行 GC 日志分析之外,稍微修改一下,还可以用作其他用途:

  • 比如让缓存的对象变多,在限制堆内存的情况下,就可以模拟“内存溢出”。

  • 增加运行时长,比如加到 30 分钟或者更长,我们就可以用前面介绍过的 VisualVM 等工具来实时监控和观察。

  • 当然,我们也可以使用全局静态变量来缓存,用来模拟“内存泄漏”,以及进行堆内存 Dump 的试验和分析。

  • 加大每次生成的数组的大小,可以用来模拟“大对象/巨无霸对象”(大对象/巨无霸对象主要是 G1 中的概念,比如超过 1MB 的数组,具体情况在后面的内容中再进行探讨)。

常用的 GC 参数

我们从简单到复杂,一步一步来验证前面学习的知识,学会使用,加深巩固。

启动示例程序

如果是在 IDEA、Eclipse 等集成开发环境中,直接在文件中点击鼠标右键,选择“Run…”即可执行。

如果使用 JDK 命令行,则可以使用 javac 工具来编译,使用 java 命令来执行(还记得吗?JDK 8 以上版本,这两个命令可以合并成一个):

$ javac demo/jvm0204/*.java
$ java demo.jvm0204.GCLogAnalysis
正在执行...
执行结束!共生成对象次数:1423

程序执行 1 秒钟就自动结束了,因为没有指定任何启动参数,所以输出的日志内容也很简单。

我们依次加上这些参数来看看效果。

输出 GC 日志详情

然后加上启动参数 -XX:+PrintGCDetails,打印 GC 日志详情,再次执行示例。

IDEA 等集成开发环境可以在“VM options”中指定启动参数,参考前面的内容。注意不要有多余的空格。

java -XX:+PrintGCDetails demo.jvm0204.GCLogAnalysis

执行结果摘录如下:

正在执行...
[GC (Allocation Failure)
  [PSYoungGen: 65081K->10728K(76288K)]  65081K->27102K(251392K), 0.0112478 secs]
  [Times: user=0.03 sys=0.02, real=0.01 secs]
......此处省略了多行
[Full GC (Ergonomics)
  [PSYoungGen: 80376K->0K(872960K)]
  [ParOldGen: 360220K->278814K(481280K)]  440597K->278814K(1354240K),
  [Metaspace: 3443K->3443K(1056768K)],
  0.0406179 secs]
  [Times: user=0.23 sys=0.01, real=0.04 secs]
执行结束!共生成对象次数:746
Heap
 PSYoungGen total 872960K, used 32300K [0x000000076ab00000, 0x00000007b0180000, 0x00000007c0000000)
  eden space 792576K, 4% used [0x000000076ab00000,0x000000076ca8b370,0x000000079b100000)
  from space 80384K, 0% used [0x00000007a3800000,0x00000007a3800000,0x00000007a8680000)
  to space 138240K, 0% used [0x000000079b100000,0x000000079b100000,0x00000007a3800000)
 ParOldGen total 481280K, used 278814K [0x00000006c0000000, 0x00000006dd600000, 0x000000076ab00000)
  object space 481280K, 57% used [0x00000006c0000000,0x00000006d1047b10,0x00000006dd600000)
 Metaspace used 3449K, capacity 4494K, committed 4864K, reserved 1056768K
  class space used 366K, capacity 386K, committed 512K, reserved 1048576K

可以看到,使用启动参数 -XX:+PrintGCDetails,发生 GC 时会输出相关的 GC 日志。

这个参数的格式为: -XX:+,这是一个布尔值开关。

在程序执行完成后、JVM 关闭前,还会输出各个内存池的使用情况,从最后面的输出中可以看到。

下面我们来简单解读上面输出的堆内存信息。

Heap 堆内存使用情况

PSYoungGen total 872960K, used 32300K [0x......)
 eden space 792576K, 4% used [0x......)
 from space 80384K, 0% used [0x......)
 to space 138240K, 0% used [0x......)

PSYoungGen,年轻代总计 872960K,使用量 32300K,后面的方括号中是内存地址信息。

  • 其中 eden space 占用了 792576K,其中 4% used

  • 其中 from space 占用了 80384K,其中 0% used

  • 其中 to space 占用了 138240K,其中 0% used

ParOldGen total 481280K, used 278814K [0x......)
 object space 481280K, 57% used [0x......)

ParOldGen,老年代总计 total 481280K,使用量 278814K。

  • 其中 object space 占用了 481280K,其中 57% used

Metaspace used 3449K, capacity 4494K, committed 4864K, reserved 1056768K
 class space used 366K, capacity 386K, committed 512K, reserved 1048576K

Metaspace,元数据区总计使用了 3449K,容量是 4494K,JVM 保证可用的大小是 4864K,保留空间 1GB 左右。

  • 其中 class space 使用了 366K,capacity 386K

指定 GC 日志文件

我们在前面的基础上,加上启动参数 -Xloggc:gc.demo.log,再次执行。

# 请注意命令行启动时没有换行,此处是手工排版
java -Xloggc:gc.demo.log -XX:+PrintGCDetails
 demo.jvm0204.GCLogAnalysis

提示:从 JDK 8 开始,支持使用 %p%t 等占位符来指定 GC 输出文件,分别表示进程 pid 和启动时间戳。

例如:-Xloggc:gc.%p.log-Xloggc:gc-%t.log

在某些情况下,将每次 JVM 执行的 GC 日志输出到不同的文件可以方便排查问题。

如果业务访问量大,导致 GC 日志文件太大,可以开启 GC 日志轮换,分割成多个文件,可以参考:

https://blog.gceasy.io/2016/11/15/rotating-gc-log-files

执行后在命令行输出的结果如下:

正在执行...
执行结束!共生成对象次数:1327

GC 日志哪去了?

查看当前工作目录,可以发现多了一个文件 gc.demo.log。 如果是 IDE 开发环境,gc.demo.log 文件可能在项目的根目录下。 当然,我们也可以指定 GC 日志文件存放的绝对路径,比如 -Xloggc:/var/log/gc.demo.log 等形式。

gc.demo.log 文件的内容如下:

Java HotSpot(TM) 64-Bit Server VM (25.162-b12) ......
Memory: 4k page,physical 16777216k(1519448k free)

/proc/meminfo:

CommandLine flags:
  -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296
  -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
  -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
  -XX:+UseParallelGC
0.310: [GC (Allocation Failure)
  [PSYoungGen: 61807K->10732K(76288K)]
  61807K->22061K(251392K), 0.0094195 secs]
  [Times: user=0.02 sys=0.02, real=0.01 secs]
0.979: [Full GC (Ergonomics)
  [PSYoungGen: 89055K->0K(572928K)]
  [ParOldGen: 280799K->254491K(434176K)]
  369855K->254491K(1007104K),
  [Metaspace: 3445K->3445K(1056768K)],
  0.0362652 secs]
  [Times: user=0.20 sys=0.01, real=0.03 secs]
...... 此处省略部分内容
Heap
...... 堆内存信息格式请参考前面的日志

我们可以发现,加上 -Xloggc: 参数之后,GC 日志信息输出到日志文件中。

文件里最前面是 JVM 相关信息,比如内存页面大小、物理内存大小、剩余内存等信息。

然后是 CommandLine flags 这部分内容。在分析 GC 日志文件时,命令行参数也是一项重要的参考。因为可能你拿到了日志文件,却不知道线上的配置,日志文件中打印了这个信息,能有效减少分析排查时间。

指定 -Xloggc: 参数,自动加上了 -XX:+PrintGCTimeStamps 配置。观察 GC 日志文件可以看到,每一行前面多了一个时间戳(如 0.310:),表示 JVM 启动后经过的时间(单位秒)。

细心的同学还可以发现,JDK 8 默认使用的垃圾收集器参数:-XX:+UseParallelGC

打印 GC 事件发生的日期和时间

我们在前面的基础上,加上启动参数 -XX:+PrintGCDateStamps,再次执行。

java -Xloggc:gc.demo.log -XX:+PrintGCDetails
 -XX:+PrintGCDateStamps demo.jvm0204.GCLogAnalysis

执行完成后,GC 日志文件中的内容摘录如下:

...... 省略多行
CommandLine flags:
  -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296
  -XX:+PrintGC -XX:+PrintGCDateStamps
  -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
  -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
  -XX:+UseParallelGC
2019-12-15T15:09:59.235-0800: 0.296:
  [GC (Allocation Failure)
    [PSYoungGen: 63844K->10323K(76288K)]
    63844K->20481K(251392K),
    0.0087896 secs]
  [Times: user=0.02 sys=0.02, real=0.01 secs]
2019-12-15T15:09:59.889-0800: 0.951:
  [Full GC (Ergonomics)
    [PSYoungGen: 81402K->0K(577536K)]
    [ParOldGen: 270176K->261230K(445952K)]
    351579K->261230K(1023488K),
    [Metaspace: 3445K->3445K(1056768K)],
    0.0369622 secs]
  [Times: user=0.19 sys=0.00, real=0.04 secs]
Heap
  .......省略内容参考前面的格式

可以看到,加上 -XX:+PrintGCDateStamps 参数之后,GC 日志每一行前面,都打印了 GC 发生时的具体时间。如 2019-12-15T15:09:59.235-0800 表示的是“东 8 区时间 2019 年 12 月 15 日 15:09:59 秒.235 毫秒”。

指定堆内存的大小

从前面的示例中可以看到 GC 日志文件中输出的 CommandLine flags 信息。

即使我们没有指定堆内存,JVM在启动时也会自动算出一个默认值出来。例如:-XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 是笔者机器上的默认值,等价于 -Xms256m -Xmx4g 配置。

我们现在继续增加参数,这次加上启动参数 -Xms512m -Xmx512m,再次执行。

java -Xms512m -Xmx512m
 -Xloggc:gc.demo.log -XX:+PrintGCDetails
 -XX:+PrintGCDateStamps demo.jvm0204.GCLogAnalysis

此时输出的 GC 日志文件内容摘录如下:

......
CommandLine flags:
  -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=536870912
  -XX:+PrintGC -XX:+PrintGCDateStamps
  -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
  -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
  -XX:+UseParallelGC
2019-12-15T15:15:09.677-0800: 0.358:
  [GC (Allocation Failure)
    [PSYoungGen: 129204K->21481K(153088K)]
    129204K->37020K(502784K), 0.0121865 secs]
  [Times: user=0.03 sys=0.03, real=0.01 secs]
2019-12-15T15:15:10.058-0800: 0.739:
  [Full GC (Ergonomics)
    [PSYoungGen: 20742K->0K(116736K)]
    [ParOldGen: 304175K->247922K(349696K)]
    324918K->247922K(466432K),
    [Metaspace: 3444K->3444K(1056768K)],
    0.0319225 secs]
  [Times: user=0.18 sys=0.01, real=0.04 secs]

此时堆内存的初始值和最大值都是 512MB。具体的参数可根据实际需要配置,我们为了演示,使用了一个较小的堆内存配置。

指定垃圾收集器

一般来说,使用 JDK 8 时我们可以使用以下几种垃圾收集器:

-XX:+UseSerialGC
-XX:+UseParallelGC
-XX:+UseParallelGC -XX:+UseParallelOldGC
-XX:+UseConcMarkSweepGC
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+UseG1GC

它们都是什么意思呢,我们再简单回顾一下:

  • 使用串行垃圾收集器:-XX:+UseSerialGC

  • 使用并行垃圾收集器:-XX:+UseParallelGC 和 -XX:+UseParallelGC -XX:+UseParallelOldGC 是等价的,可以通过 GC 日志文件中的 flags 看出来。

  • 使用 CMS 垃圾收集器:-XX:+UseConcMarkSweepGC 和 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC 是等价的。但如果只指定 -XX:+UseParNewGC 参数则老年代 GC 会使用 SerialGC。使用CMS时,命令行参数中会自动计算出年轻代、老年代的初始值和最大值,以及最大晋升阈值等信息(例如 -XX:MaxNewSize=178958336 -XX:NewSize=178958336 -XX:OldSize=357912576)。

  • 使用 G1 垃圾收集器:-XX:+UseG1GC。原则上不能指定 G1 垃圾收集器的年轻代大小,否则不仅是画蛇添足,更是自废武功了。因为 G1 的回收方式是小批量划定区块(region)进行,可能一次普通 GC 中既有年轻代又有老年代,可能某个区块一会是老年代,一会又变成年轻代了。

如果使用不支持的 GC 组合,会怎么样呢?答案是会启动失败,报 fatal 错误,有兴趣的同学可以试一下。

下一节会依次演示各种垃圾收集器的使用,并采集和分析他们产生的日志。它们的格式差距并不大,学会分析一种 GC 日志之后,就可以举一反三,对于其他类型的 GC 日志,基本上也能看懂各项信息的大概意思。

其他参数

JVM 里还有一些 GC 日志相关的参数,例如:

  • -XX:+PrintGCApplicationStoppedTime 可以输出每次 GC 的持续时间和程序暂停时间;

  • -XX:+PrintReferenceGC 输出 GC 清理了多少引用类型。

这里就不再赘述,想了解配置详情的,可以回头复习前面的章节。

说明:大部分情况下,配置 GC 参数并不是越多越好。原则上只配置最重要的几个参数即可,其他的都保持默认值,除非你对系统的业务特征有了深入的分析和了解,才需要进行某些细微参数的调整。毕竟,古语有云:“过早优化是万恶之源”。

GC 事件的类型简介

一般来说,垃圾收集事件(Garbage Collection events)可以分为三种类型:

  • Minor GC(小型 GC)

  • Major GC(大型 GC)

  • Full GC(完全 GC)

虽然 Minor GC,Major GC 和 Full GC 这几个词汇到处都在用,但官方并没有给出标准的定义。这些术语出现在官方的各种分析工具和垃圾收集日志中,并不是很统一。官方的文档和工具之间也常常混淆,这些混淆甚至根植于标准的 JVM 工具中。

MinorGC 称为“小型 GC”,还是“次要GC”更合理呢?

辨析:在大部分情况下,发生在年轻代的 Minor GC 次数更多,有些文章将次数更多的 GC 称为“次要 GC”明显是不太合理的。

在这里,我们将 Minor GC 翻译为“小型 GC”,而不是“次要 GC”;将 Major GC 翻译为“大型GC”而不是“主要 GC”;Full GC 翻译为完全 GC;有时候也直接称为 Full GC。

其实这也是因为专有名词在中英文翻译的时候,可能会有多个英语词汇对应一个中文词语,也会有一个英文词汇对应多个中文词语,要看具体情况而定。

比如一个类似的情况:Major Version 和 Minor Version,这两个名词一般翻译为“主要版本”和“次要版本”。这当然没问题,大家都能理解,一看就知道什么意思。甚至直接翻译为“大版本号”和“小版本号”也是能讲得通的。

本节简单介绍了这几种事件类型及其区别,下面我们来看看这些事件类型的具体细节。

Minor GC(小型 GC)

收集年轻代内存的 GC 事件称为 Minor GC。关于 Minor GC 事件,我们需要了解一些相关的内容:

  1. 当 JVM 无法为新对象分配内存空间时就会触发 Minor GC( 一般就是 Eden 区用满了)。如果对象的分配速率很快,那么 Minor GC 的次数也就会很多,频率也就会很快。

  2. Minor GC 事件不处理老年代,所以会把所有从老年代指向年轻代的引用都当做 GC Root。从年轻代指向老年代的引用则在标记阶段被忽略。

  3. 与我们一般的认知相反,Minor GC 每次都会引起 STW 停顿(stop-the-world),挂起所有的应用线程。对大部分应用程序来说,Minor GC 的暂停时间可以忽略不计,因为 Eden 区里面的对象大部分都是垃圾,也不怎么复制到存活区/老年代。但如果不符合这种情况,那么很多新创建的对象就不能被 GC 清理,Minor GC 的停顿时间就会增大,就会产生比较明显的 GC 性能影响。

简单定义:Minor GC 清理的是年轻代,又或者说 Minor GC 就是“年轻代 GC”(Young GC,简称 YGC)。

Major GC vs. Full GC

值得一提的是,这几个术语都没有正式的定义–无论是在 JVM 规范中还是在 GC 论文中。

我们知道,除了 Minor GC 外,另外两种 GC 事件则是:

  • Major GC(大型 GC):清理老年代空间(Old Space)的 GC 事件。

  • Full GC(完全 GC):清理整个堆内存空间的 GC 事件,包括年轻代空间和老年代空间。

其实 Major GC 和 Full GC 有时候并不能很好地区分。更复杂的情况是,很多 Major GC 是由 Minor GC 触发的,所以很多情况下这两者是不可分离的。

另外,像 G1 这种垃圾收集算法,是每次找一小部分区域来进行清理,这部分区域中可能有一部分是年轻代,另一部分区域属于老年代。

所以我们不要太纠结具体是叫 Major GC 呢还是叫 Full GC,它们一般都会造成单次较长时间的 STW 暂停。所以我们需要关注的是:某次 GC 事件,是暂停了所有线程、进而对系统造成了性能影响呢,还是与其他业务线程并发执行、暂停时间几乎可以忽略不计。

来源:《JVM 核心技术 32 讲》

Mac通用命令面板——快捷猫 (Shortcat)

2025-01-10 21:50:43

快捷猫 (Shortcat) 是一款适用于Mac的通用命令面板,专为键盘操作设计,无需鼠标,即可熟练操作 macOS和高效完成多种任务。它通过索引用户界面,将按钮点击、文本字段聚焦、菜单命令调用等功能整合到一个通用命令面板中,极大地提升了操作效率。Shortcat 支持模糊搜索和同义词匹配,可快速定位菜单项、窗口标题和表情符号,为用户节省操作时间,减少认知负担。兼容主流浏览器和 Electron 应用,Shortcat 提供了极致流畅的键盘体验,是 macOS 用户优化工作流的绝佳选择。

Shortcat:Manipulate macOS masterfully, minus the mouse.The universal command palette for your Mac.

  • Shortcat indexes your Mac's user interface and makes them available to you in a powerful command palette.

  • Click buttons, focus text fields, invoke menu commands, switch windows, and more; no mouse required.

  • Shortcat enables you to operate your Mac faster, and with less cognitive overhead.

dns-demo-3ea8879d21aee5e98f833e50d26ec1d3.gif

蛮子五杀

2025-01-04 02:38:22

我的大刀早已饥渴难耐!

_share_auto_2025_1_4_1_34_36.png

[video dplayer="true" autoplay="false" src="https://cdn.chegva.com/ueditor/php/upload/video/20250104/1735928786889849.mp4" loop="false" preload="true" theme="#b7daff" mutex="true" iconsColor="#ffffff"]